-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sil-devirtualizer] Improve devirtualization of witness_method instru…
…ctions. Handle such cases like partial applications of witness methods and applications of witness methods with substitutions. Some of these uses-cases occur when there is a protocol defining an operator, a generic struct conforming to this protocol, and the operator conformance of this struct is expressed as a global function.
- Loading branch information
Showing
10 changed files
with
160 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine | FileCheck %s | ||
sil_stage canonical | ||
|
||
import Builtin | ||
import Swift | ||
import SwiftShims | ||
|
||
protocol CanAdd { | ||
func +(lhs: Self, rhs: Self) -> Self | ||
} | ||
|
||
extension Int64 : CanAdd { | ||
} | ||
|
||
struct S<T> : CanAdd { | ||
} | ||
|
||
func +<T>(lhs: S<T>, rhs: S<T>) -> S<T> | ||
|
||
|
||
sil hidden [transparent] [thunk] @operator_plus_static_non_generic_witness_for_S : $@convention(thin) <T where T : CanAdd> (@out S<T>, @in S<T>, @in S<T>, @thick S<T>.Type) -> () { | ||
bb0(%0 : $*S<T>, %1 : $*S<T>, %2 : $*S<T>, %3 : $@thick S<T>.Type) : | ||
%17 = tuple () | ||
return %17 : $() | ||
} | ||
|
||
sil hidden [transparent] [thunk] @operator_plus_static_non_generic_witness : $@convention(witness_method) (@out Int64, @in Int64, @in Int64, @thick Int64.Type) -> () { | ||
bb0(%0 : $*Int64, %1 : $*Int64, %2 : $*Int64, %3 : $@thick Int64.Type): | ||
%4 = struct_element_addr %1 : $*Int64, #Int64._value | ||
%5 = load %4 : $*Builtin.Int64 | ||
%6 = struct_element_addr %2 : $*Int64, #Int64._value | ||
%7 = load %6 : $*Builtin.Int64 | ||
%8 = integer_literal $Builtin.Int1, -1 | ||
%9 = builtin "sadd_with_overflow_Int64"(%5 : $Builtin.Int64, %7 : $Builtin.Int64, %8 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) | ||
%10 = tuple_extract %9 : $(Builtin.Int64, Builtin.Int1), 0 | ||
%11 = tuple_extract %9 : $(Builtin.Int64, Builtin.Int1), 1 | ||
cond_fail %11 : $Builtin.Int1 | ||
%15 = struct $Int64 (%10 : $Builtin.Int64) | ||
store %15 to %0 : $*Int64 | ||
%17 = tuple () | ||
return %17 : $() | ||
} | ||
|
||
// Test that this partial application of a function reference referring to static non generic witness does not crash the IRGen. | ||
// Such code may be produced e.g. when users refer to global operators defined on builtin types. | ||
// CHECK-LABEL: sil hidden @test_partial_apply_of_static_witness | ||
sil hidden @test_partial_apply_of_static_witness : $@convention(thin) () -> @callee_owned (@out Int64, @in Int64, @in Int64) -> () { | ||
bb0: | ||
%1 = metatype $@thick Int64.Type | ||
%2 = function_ref @operator_plus_static_non_generic_witness : $@convention(witness_method) (@out Int64, @in Int64, @in Int64, @thick Int64.Type) -> () | ||
%3 = partial_apply %2(%1) : $@convention(witness_method) (@out Int64, @in Int64, @in Int64, @thick Int64.Type) -> () | ||
return %3 : $@callee_owned (@out Int64, @in Int64, @in Int64) -> () | ||
} | ||
|
||
// Test that this partial application of witness_method can be devirtualized. | ||
// CHECK-LABEL: sil hidden @test_devirt_of_partial_apply_of_witness_method | ||
// CHECK-NOT: witness_method $S<Int64>, #CanAdd."+"!1 | ||
// CHECK: function_ref @operator_plus_static_non_generic_witness_for_S | ||
// CHECK: partial_apply | ||
// CHECK: return | ||
sil hidden @test_devirt_of_partial_apply_of_witness_method : $@convention(thin) () -> @callee_owned (@out S<Int64>, @in S<Int64>, @in S<Int64>) -> () { | ||
bb0: | ||
%1 = metatype $@thick S<Int64>.Type | ||
%2 = witness_method $S<Int64>, #CanAdd."+"!1 : $@convention(witness_method) <τ_0_0 where τ_0_0 : CanAdd> (@out τ_0_0, @in τ_0_0, @in τ_0_0, @thick τ_0_0.Type) -> () | ||
%3 = partial_apply %2<S<Int64>>(%1) : $@convention(witness_method) <τ_0_0 where τ_0_0 : CanAdd> (@out τ_0_0, @in τ_0_0, @in τ_0_0, @thick τ_0_0.Type) -> () | ||
return %3 : $@callee_owned (@out S<Int64>, @in S<Int64>, @in S<Int64>) -> () | ||
} | ||
|
||
// Test that this application of witness_method can be devirtualized. | ||
// CHECK-LABEL: sil hidden @test_devirt_of_apply_of_witness_method | ||
// CHECK-NOT: witness_method $S<Int64>, #CanAdd."+"!1 | ||
// CHECK: function_ref @operator_plus_static_non_generic_witness_for_S | ||
// CHECK: apply | ||
// CHECK: return | ||
sil hidden @test_devirt_of_apply_of_witness_method : $@convention(thin) (@in S<Int64>) -> S<Int64> { | ||
bb0(%0 : $*S<Int64>): | ||
%1 = alloc_stack $S<Int64> | ||
%5 = metatype $@thick S<Int64>.Type | ||
%6 = witness_method $S<Int64>, #CanAdd."+"!1 : $@convention(witness_method) <τ_0_0 where τ_0_0 : CanAdd> (@out τ_0_0, @in τ_0_0, @in τ_0_0, @thick τ_0_0.Type) -> () | ||
%7 = apply %6<S<Int64>>(%1#1, %0, %0, %5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : CanAdd> (@out τ_0_0, @in τ_0_0, @in τ_0_0, @thick τ_0_0.Type) -> () | ||
%8 = load %1#1: $*S<Int64> | ||
dealloc_stack %1#0 : $*@local_storage S<Int64> | ||
return %8 : $S<Int64> | ||
} | ||
|
||
sil_witness_table hidden Int64: CanAdd module Test { | ||
method #CanAdd."+"!1: @operator_plus_static_non_generic_witness | ||
} | ||
|
||
sil_witness_table hidden <E where E : CanAdd> S<E>: CanAdd module Test { | ||
method #CanAdd."+"!1: @operator_plus_static_non_generic_witness_for_S | ||
} | ||
|
3 comments
on commit 5cc14ab
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@swiftix Roman, in the future please split changes like this into several commits. I would split this commit into:
- The IRGen fix
- Changes to SILInstruction
- Changes to the Devirtualizer and Inliner.
- Changes to SILCombine + Testcase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rjmccall John, IRGen changes are based on our discussion. Would you mind reviewing this commit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IRGen changes LGTM; a couple style suggestions.
Please just merge this case into the identical case block below.