Skip to content

Turn off speculative devirtualization by default. #29359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/SILOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class SILOptions {
/// purposes.
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
///
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ def disable_ossa_opts : Flag<["-"], "disable-ossa-opts">,
def disable_sil_partial_apply : Flag<["-"], "disable-sil-partial-apply">,
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
: Flag<["-"], "enable-ownership-stripping-after-serialization">,
HelpText<"Strip ownership after serialization">;
Expand Down
1 change: 1 addition & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,

Opts.EnableARCOptimizations &= !Args.hasArg(OPT_disable_arc_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.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);
Expand Down
4 changes: 3 additions & 1 deletion lib/SILOptimizer/PassManager/PassPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,9 @@ static void addClosureSpecializePassPipeline(SILPassPipelinePlan &P) {
P.addStackPromotion();

// Speculate virtual call targets.
P.addSpeculativeDevirtualization();
if (P.getOptions().EnableSpeculativeDevirtualization) {
P.addSpeculativeDevirtualization();
}

// There should be at least one SILCombine+SimplifyCFG between the
// ClosureSpecializer, etc. and the last inliner. Cleaning up after these
Expand Down
1 change: 1 addition & 0 deletions lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ namespace {
void run() override {

auto &CurFn = *getFunction();

// Don't perform speculative devirtualization at -Os.
if (CurFn.optimizeForSize())
return;
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_base_class.swift
Original file line number Diff line number Diff line change
@@ -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 } }

Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_covariant_return.swift
Original file line number Diff line number Diff line change
@@ -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
// protocol conformances with covariant return types correctly. The verifier
Expand Down
4 changes: 2 additions & 2 deletions test/SILOptimizer/devirt_default_case.swift
Original file line number Diff line number Diff line change
@@ -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 -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 %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 -enable-testing %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s

@_silgen_name("action")
func action(_ n:Int) -> ()
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_protocol_method_invocations.swift
Original file line number Diff line number Diff line change
@@ -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 {
func f()
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_speculate.swift
Original file line number Diff line number Diff line change
@@ -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: %target-swift-frontend %/s -parse-as-library -Osize -emit-sil | %FileCheck %s --check-prefix=OSIZE
//
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_speculative_init.swift
Original file line number Diff line number Diff line change
@@ -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
//
// Test speculative devirtualization.
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_speculative_nested.swift
Original file line number Diff line number Diff line change
@@ -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
//
// Test speculative devirtualization.
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_unbound_generic.swift
Original file line number Diff line number Diff line change
@@ -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),
// because it is an "apply" with replacement types that contain
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_value_metatypes.swift
Original file line number Diff line number Diff line change
@@ -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 {
@inline(never)
Expand Down
3 changes: 1 addition & 2 deletions test/SILOptimizer/inline_cache_and_arc.swift
Original file line number Diff line number Diff line change
@@ -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

// Test inline cache with a global class. Make sure the retain|release pair
Expand All @@ -19,7 +19,6 @@ public func testit() {
// CHECK-LABEL: sil @{{.*}}testityyF
// CHECK: bb0:
// CHECK-NOT: {{.*(retain|release).*}}
// CHECK: checked_cast_br
// CHECK: bb1{{.*}}:
// CHECK-NOT: {{.*(retain|release).*}}
// CHECK: return
Expand Down
22 changes: 11 additions & 11 deletions test/SILOptimizer/opt_mode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,6 @@ class B : A {

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: [[M:%[0-9]+]] = class_method
// CHECK: [[A:%[0-9]+]] = apply [[M]]
Expand All @@ -46,6 +36,16 @@ func test_onone(_ a: A) -> Int {
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 [[NOSIZE_ATTR]] = { "
6 changes: 6 additions & 0 deletions tools/sil-opt/SILOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ static llvm::cl::opt<bool>
VerifyExclusivity("enable-verify-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 {
enum EnforceExclusivityMode {
Unchecked, // static only
Expand Down Expand Up @@ -376,6 +380,8 @@ int main(int argc, char **argv) {
}
}

SILOpts.EnableSpeculativeDevirtualization = EnableSpeculativeDevirtualization;

serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
Invocation.setUpInputForSILTool(InputFilename, ModuleName,
Expand Down