mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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
This commit is contained in:
@@ -57,6 +57,10 @@ public:
|
|||||||
/// purposes.
|
/// purposes.
|
||||||
bool EnableOSSAOptimizations = true;
|
bool EnableOSSAOptimizations = true;
|
||||||
|
|
||||||
|
/// Controls whether to turn on speculative devirtualization.
|
||||||
|
/// It is turned off by default.
|
||||||
|
bool EnableSpeculativeDevirtualization = false;
|
||||||
|
|
||||||
/// Should we run any SIL performance optimizations
|
/// Should we run any SIL performance optimizations
|
||||||
///
|
///
|
||||||
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.
|
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.
|
||||||
|
|||||||
@@ -282,6 +282,9 @@ def disable_ossa_opts : Flag<["-"], "disable-ossa-opts">,
|
|||||||
def disable_sil_partial_apply : Flag<["-"], "disable-sil-partial-apply">,
|
def disable_sil_partial_apply : Flag<["-"], "disable-sil-partial-apply">,
|
||||||
HelpText<"Disable use of partial_apply in SIL generation">;
|
HelpText<"Disable use of partial_apply in SIL generation">;
|
||||||
|
|
||||||
|
def enable_spec_devirt : Flag<["-"], "enable-spec-devirt">,
|
||||||
|
HelpText<"Enable speculative devirtualization pass.">;
|
||||||
|
|
||||||
def enable_ownership_stripping_after_serialization
|
def enable_ownership_stripping_after_serialization
|
||||||
: Flag<["-"], "enable-ownership-stripping-after-serialization">,
|
: Flag<["-"], "enable-ownership-stripping-after-serialization">,
|
||||||
HelpText<"Strip ownership after serialization">;
|
HelpText<"Strip ownership after serialization">;
|
||||||
|
|||||||
@@ -959,6 +959,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
|
|||||||
|
|
||||||
Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_opts);
|
Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_opts);
|
||||||
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
|
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
|
||||||
|
Opts.EnableSpeculativeDevirtualization |= Args.hasArg(OPT_enable_spec_devirt);
|
||||||
Opts.DisableSILPerfOptimizations |= Args.hasArg(OPT_disable_sil_perf_optzns);
|
Opts.DisableSILPerfOptimizations |= Args.hasArg(OPT_disable_sil_perf_optzns);
|
||||||
Opts.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
|
Opts.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
|
||||||
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);
|
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);
|
||||||
|
|||||||
@@ -488,7 +488,9 @@ static void addClosureSpecializePassPipeline(SILPassPipelinePlan &P) {
|
|||||||
P.addStackPromotion();
|
P.addStackPromotion();
|
||||||
|
|
||||||
// Speculate virtual call targets.
|
// Speculate virtual call targets.
|
||||||
P.addSpeculativeDevirtualization();
|
if (P.getOptions().EnableSpeculativeDevirtualization) {
|
||||||
|
P.addSpeculativeDevirtualization();
|
||||||
|
}
|
||||||
|
|
||||||
// There should be at least one SILCombine+SimplifyCFG between the
|
// There should be at least one SILCombine+SimplifyCFG between the
|
||||||
// ClosureSpecializer, etc. and the last inliner. Cleaning up after these
|
// ClosureSpecializer, etc. and the last inliner. Cleaning up after these
|
||||||
|
|||||||
@@ -596,6 +596,7 @@ namespace {
|
|||||||
void run() override {
|
void run() override {
|
||||||
|
|
||||||
auto &CurFn = *getFunction();
|
auto &CurFn = *getFunction();
|
||||||
|
|
||||||
// Don't perform speculative devirtualization at -Os.
|
// Don't perform speculative devirtualization at -Os.
|
||||||
if (CurFn.optimizeForSize())
|
if (CurFn.optimizeForSize())
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
|
// RUN: %target-swift-frontend -enable-spec-devirt -O -emit-sil %s | %FileCheck %s
|
||||||
|
|
||||||
public class Base1 { @inline(never) func f() -> Int { return 0 } }
|
public class Base1 { @inline(never) func f() -> Int { return 0 } }
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// 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
|
// 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
|
||||||
|
|
||||||
// Make sure that we can dig all the way through the class hierarchy and
|
// Make sure that we can dig all the way through the class hierarchy and
|
||||||
// protocol conformances with covariant return types correctly. The verifier
|
// protocol conformances with covariant return types correctly. The verifier
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
|
// 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
|
||||||
// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil -enable-testing %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
|
// 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
|
||||||
|
|
||||||
@_silgen_name("action")
|
@_silgen_name("action")
|
||||||
func action(_ n:Int) -> ()
|
func action(_ n:Int) -> ()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-frontend -module-name devirt_protocol_method_invocations -O -Xllvm -sil-disable-pass=ExistentialSpecializer -emit-sil %s | %FileCheck %s
|
// RUN: %target-swift-frontend -module-name devirt_protocol_method_invocations -enable-spec-devirt -O -Xllvm -sil-disable-pass=ExistentialSpecializer -emit-sil %s | %FileCheck %s
|
||||||
|
|
||||||
protocol PPP {
|
protocol PPP {
|
||||||
func f()
|
func f()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// RUN: %target-swift-frontend %/s -parse-as-library -O -emit-sil -save-optimization-record-path %t.opt.yaml | %FileCheck %s
|
// RUN: %target-swift-frontend %/s -parse-as-library -enable-spec-devirt -O -emit-sil -save-optimization-record-path %t.opt.yaml | %FileCheck %s
|
||||||
// RUN: %FileCheck -check-prefix=YAML -input-file=%t.opt.yaml %s
|
// RUN: %FileCheck -check-prefix=YAML -input-file=%t.opt.yaml %s
|
||||||
// RUN: %target-swift-frontend %/s -parse-as-library -Osize -emit-sil | %FileCheck %s --check-prefix=OSIZE
|
// RUN: %target-swift-frontend %/s -parse-as-library -Osize -emit-sil | %FileCheck %s --check-prefix=OSIZE
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-frontend %s -parse-as-library -O -emit-sil | %FileCheck %s
|
// RUN: %target-swift-frontend %s -parse-as-library -enable-spec-devirt -O -emit-sil | %FileCheck %s
|
||||||
// RUN: %target-swift-frontend %s -parse-as-library -Osize -emit-sil
|
// RUN: %target-swift-frontend %s -parse-as-library -Osize -emit-sil
|
||||||
//
|
//
|
||||||
// Test speculative devirtualization.
|
// Test speculative devirtualization.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -O -emit-sil | %FileCheck %s
|
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -enable-spec-devirt -O -emit-sil | %FileCheck %s
|
||||||
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -Osize -emit-sil
|
// RUN: %target-swift-frontend -module-name devirt_speculative_nested %s -parse-as-library -Osize -emit-sil
|
||||||
//
|
//
|
||||||
// Test speculative devirtualization.
|
// Test speculative devirtualization.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -O %s | %FileCheck %s
|
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -enable-spec-devirt -O %s | %FileCheck %s
|
||||||
|
|
||||||
// We used to crash on this when trying to devirtualize t.boo(a, 1),
|
// We used to crash on this when trying to devirtualize t.boo(a, 1),
|
||||||
// because it is an "apply" with replacement types that contain
|
// because it is an "apply" with replacement types that contain
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-frontend -module-name devirt_value_metatypes -emit-sil -O %s | %FileCheck %s
|
// RUN: %target-swift-frontend -module-name devirt_value_metatypes -emit-sil -enable-spec-devirt -O %s | %FileCheck %s
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
@inline(never)
|
@inline(never)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// RUN: %target-swift-frontend -parse-as-library -O -emit-sil %s | %FileCheck %s
|
// RUN: %target-swift-frontend -parse-as-library -enable-spec-devirt -O -emit-sil %s | %FileCheck %s
|
||||||
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib,CPU=x86_64
|
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib,CPU=x86_64
|
||||||
|
|
||||||
// Test inline cache with a global class. Make sure the retain|release pair
|
// Test inline cache with a global class. Make sure the retain|release pair
|
||||||
@@ -19,7 +19,6 @@ public func testit() {
|
|||||||
// CHECK-LABEL: sil @{{.*}}testityyF
|
// CHECK-LABEL: sil @{{.*}}testityyF
|
||||||
// CHECK: bb0:
|
// CHECK: bb0:
|
||||||
// CHECK-NOT: {{.*(retain|release).*}}
|
// CHECK-NOT: {{.*(retain|release).*}}
|
||||||
// CHECK: checked_cast_br
|
|
||||||
// CHECK: bb1{{.*}}:
|
// CHECK: bb1{{.*}}:
|
||||||
// CHECK-NOT: {{.*(retain|release).*}}
|
// CHECK-NOT: {{.*(retain|release).*}}
|
||||||
// CHECK: return
|
// CHECK: return
|
||||||
|
|||||||
@@ -15,16 +15,6 @@ class B : A {
|
|||||||
|
|
||||||
func donothing(_ x: Int) -> Int { return x }
|
func donothing(_ x: Int) -> Int { return x }
|
||||||
|
|
||||||
// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
|
|
||||||
// CHECK: checked_cast_br
|
|
||||||
// CHECK: checked_cast_br
|
|
||||||
// CHECK: }
|
|
||||||
// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
|
|
||||||
@_optimize(speed)
|
|
||||||
func test_ospeed(_ a: A) -> Int {
|
|
||||||
return donothing(a.foo(27))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: sil {{.*}} [Osize] @{{.*}}test_osize
|
// CHECK-LABEL: sil {{.*}} [Osize] @{{.*}}test_osize
|
||||||
// CHECK: [[M:%[0-9]+]] = class_method
|
// CHECK: [[M:%[0-9]+]] = class_method
|
||||||
// CHECK: [[A:%[0-9]+]] = apply [[M]]
|
// CHECK: [[A:%[0-9]+]] = apply [[M]]
|
||||||
@@ -46,6 +36,16 @@ func test_onone(_ a: A) -> Int {
|
|||||||
return donothing(a.foo(27))
|
return donothing(a.foo(27))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
|
||||||
|
// CHECK: [[M:%[0-9]+]] = class_method
|
||||||
|
// CHECK: [[A:%[0-9]+]] = apply [[M]]
|
||||||
|
// CHECK: return [[A]]
|
||||||
|
// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
|
||||||
|
@_optimize(speed)
|
||||||
|
func test_ospeed(_ a: A) -> Int {
|
||||||
|
return donothing(a.foo(27))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "
|
|
||||||
// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize "
|
// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize "
|
||||||
|
// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ static llvm::cl::opt<bool>
|
|||||||
VerifyExclusivity("enable-verify-exclusivity",
|
VerifyExclusivity("enable-verify-exclusivity",
|
||||||
llvm::cl::desc("Verify the access markers used to enforce exclusivity."));
|
llvm::cl::desc("Verify the access markers used to enforce exclusivity."));
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool>
|
||||||
|
EnableSpeculativeDevirtualization("enable-spec-devirt",
|
||||||
|
llvm::cl::desc("Enable Speculative Devirtualization pass."));
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
enum EnforceExclusivityMode {
|
enum EnforceExclusivityMode {
|
||||||
Unchecked, // static only
|
Unchecked, // static only
|
||||||
@@ -376,6 +380,8 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SILOpts.EnableSpeculativeDevirtualization = EnableSpeculativeDevirtualization;
|
||||||
|
|
||||||
serialization::ExtendedValidationInfo extendedInfo;
|
serialization::ExtendedValidationInfo extendedInfo;
|
||||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
||||||
Invocation.setUpInputForSILTool(InputFilename, ModuleName,
|
Invocation.setUpInputForSILTool(InputFilename, ModuleName,
|
||||||
|
|||||||
Reference in New Issue
Block a user