Skip to content

Commit eb254f7

Browse files
committed
[sil-combine] Add ossa test translations that already pass given current upstreamed work.
1 parent f6c7c0d commit eb254f7

File tree

4 files changed

+319
-0
lines changed

4 files changed

+319
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
8+
/*
9+
class Foo {
10+
var m_val : Int32
11+
init(x : Int32) { m_val = x }
12+
func get() -> Int32 {return m_val}
13+
}
14+
func test_me(x : Int32) -> Foo { return Foo(x) }
15+
func main() { print(test_me(3).get()) } */
16+
17+
class Foo {
18+
var m_val: Int32
19+
init(x: Int32)
20+
func get() -> Int32
21+
}
22+
23+
//CHECK: _TF4main4mainFT_T_
24+
//CHECK: function_ref @_TFC4main3Foo3getfS0_FT_Si
25+
//CHECK: return
26+
sil [ossa] @_TF4main4mainFT_T_ : $@convention(thin) () -> () {
27+
bb0:
28+
// function_ref swift
29+
%0 = function_ref @_Ts5printFT3valSi_T_ : $@convention(thin) (Int32) -> () // user: %8
30+
%1 = integer_literal $Builtin.Int32, 3 // user: %2
31+
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %5
32+
%3 = alloc_ref $Foo // users: %6, %7, %4
33+
%3a = begin_borrow %3 : $Foo
34+
%4 = ref_element_addr %3a : $Foo, #Foo.m_val // user: %5
35+
store %2 to [trivial] %4 : $*Int32 // id: %5
36+
end_borrow %3a : $Foo
37+
%6 = class_method %3 : $Foo, #Foo.get : (Foo) -> () -> Int32, $@convention(method) (@guaranteed Foo) -> Int32 // user: %7
38+
%7 = apply %6(%3) : $@convention(method) (@guaranteed Foo) -> Int32 // user: %8
39+
%8 = apply %0(%7) : $@convention(thin) (Int32) -> ()
40+
%9 = tuple () // user: %10
41+
destroy_value %3 : $Foo
42+
return %9 : $() // id: %10
43+
}
44+
45+
sil [ossa] @_Ts5printFT3valSi_T_ : $@convention(thin) (Int32) -> ()
46+
47+
// main.Foo.get (main.Foo)() -> Swift.Int32
48+
sil [noinline] [ossa] @_TFC4main3Foo3getfS0_FT_Si : $@convention(method) (@guaranteed Foo) -> Int32 {
49+
bb0(%0 : @guaranteed $Foo):
50+
%1 = ref_element_addr %0 : $Foo, #Foo.m_val // user: %2
51+
%2 = load [trivial] %1 : $*Int32 // user: %4
52+
return %2 : $Int32 // id: %4
53+
}
54+
55+
sil_vtable Foo {
56+
#Foo.get: @_TFC4main3Foo3getfS0_FT_Si
57+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all -sil-combine %s | %FileCheck %s
2+
3+
// This file tests sil combine's canonicalization of memory.
4+
5+
class Klass {}
6+
7+
////////////////////////////
8+
// Store Canonicalization //
9+
////////////////////////////
10+
11+
// We canonicalize stores of fields of single element structs into stores of the
12+
// struct itself. The two are equivalent.
13+
14+
struct SingleEltStruct {
15+
var k: Klass
16+
}
17+
18+
// CHECK-LABEL: sil [ossa] @promote_initialization_of_single_elt_struct : $@convention(thin) (@owned Klass) -> @owned SingleEltStruct {
19+
// CHECK: bb0([[ARG:%.*]] : @owned $Klass):
20+
// CHECK: [[STACK:%.*]] = alloc_stack $SingleEltStruct
21+
// CHECK: [[STRUCT_ARG:%.*]] = struct $SingleEltStruct ([[ARG]] : $Klass)
22+
// CHECK: store [[STRUCT_ARG]] to [init] [[STACK]]
23+
// CHECK: dealloc_stack [[STACK]]
24+
// CHECK: } // end sil function 'promote_initialization_of_single_elt_struct'
25+
sil [ossa] @promote_initialization_of_single_elt_struct : $@convention(thin) (@owned Klass) -> @owned SingleEltStruct {
26+
bb0(%0 : @owned $Klass):
27+
%1 = alloc_stack $SingleEltStruct
28+
%2 = struct_element_addr %1 : $*SingleEltStruct, #SingleEltStruct.k
29+
store %0 to [init] %2 : $*Klass
30+
%3 = load [take] %1 : $*SingleEltStruct
31+
dealloc_stack %1 : $*SingleEltStruct
32+
return %3 : $SingleEltStruct
33+
}
34+
35+
struct RecursiveSingleEltStruct {
36+
var field: RecursiveSingleEltStructField
37+
}
38+
39+
struct RecursiveSingleEltStructField {
40+
var k: Klass
41+
}
42+
43+
// CHECK-LABEL: sil [ossa] @promote_initialization_of_recursive_single_elt_struct : $@convention(thin) (@owned Klass) -> () {
44+
// CHECK: bb0([[ARG:%.*]] : @owned $Klass):
45+
// CHECK: [[STACK:%.*]] = alloc_stack $RecursiveSingleEltStruct
46+
// CHECK: [[STRUCT_ARG_1:%.*]] = struct $RecursiveSingleEltStructField ([[ARG]] : $Klass)
47+
// CHECK: [[STRUCT_ARG_2:%.*]] = struct $RecursiveSingleEltStruct ([[STRUCT_ARG_1]] : $RecursiveSingleEltStructField)
48+
// CHECK: store [[STRUCT_ARG_2]] to [init] [[STACK]]
49+
// CHECK: dealloc_stack [[STACK]]
50+
// CHECK: } // end sil function 'promote_initialization_of_recursive_single_elt_struct'
51+
sil [ossa] @promote_initialization_of_recursive_single_elt_struct : $@convention(thin) (@owned Klass) -> () {
52+
bb0(%0 : @owned $Klass):
53+
%1 = alloc_stack $RecursiveSingleEltStruct
54+
%2 = struct_element_addr %1 : $*RecursiveSingleEltStruct, #RecursiveSingleEltStruct.field
55+
%3 = struct_element_addr %2 : $*RecursiveSingleEltStructField, #RecursiveSingleEltStructField.k
56+
store %0 to [init] %3 : $*Klass
57+
%4 = load [take] %1 : $*RecursiveSingleEltStruct
58+
destroy_value %4 : $RecursiveSingleEltStruct
59+
dealloc_stack %1 : $*RecursiveSingleEltStruct
60+
%9999 = tuple()
61+
return %9999 : $()
62+
}
63+
64+
struct MultipleFieldStruct {
65+
var k: Klass
66+
var field: RecursiveSingleEltStructField
67+
}
68+
69+
// CHECK-LABEL: sil [ossa] @only_promote_as_far_as_have_single_elts : $@convention(thin) (@owned Klass) -> () {
70+
// CHECK: bb0([[ARG:%.*]] :
71+
// CHECK: [[STACK:%.*]] = alloc_stack $MultipleFieldStruct
72+
// CHECK: [[MULTIPLE_FIELD_SEA:%.*]] = struct_element_addr [[STACK]]
73+
// CHECK: [[VALUE:%.*]] = struct $RecursiveSingleEltStructField ([[ARG]] : $Klass)
74+
// CHECK: store [[VALUE]] to [init] [[MULTIPLE_FIELD_SEA]]
75+
// CHECK: dealloc_stack [[STACK]]
76+
// CHECK: } // end sil function 'only_promote_as_far_as_have_single_elts'
77+
sil [ossa] @only_promote_as_far_as_have_single_elts : $@convention(thin) (@owned Klass) -> () {
78+
bb0(%0 : @owned $Klass):
79+
%1 = alloc_stack $MultipleFieldStruct
80+
%2 = struct_element_addr %1 : $*MultipleFieldStruct, #MultipleFieldStruct.field
81+
%2a = struct_element_addr %1 : $*MultipleFieldStruct, #MultipleFieldStruct.k
82+
%3 = struct_element_addr %2 : $*RecursiveSingleEltStructField, #RecursiveSingleEltStructField.k
83+
%0a = copy_value %0 : $Klass
84+
store %0a to [init] %2a : $*Klass
85+
store %0 to [init] %3 : $*Klass
86+
destroy_addr %1 : $*MultipleFieldStruct
87+
dealloc_stack %1 : $*MultipleFieldStruct
88+
%9999 = tuple()
89+
return %9999 : $()
90+
}
91+
92+
// CHECK-LABEL: sil [ossa] @perform_no_work_if_multiple_fields : $@convention(thin) (@owned RecursiveSingleEltStructField, @owned Klass) -> () {
93+
// CHECK: bb0([[ARG:%[0-9][0-9]*]] : @owned $RecursiveSingleEltStructField, [[ARG2:%.*]] : @owned
94+
// CHECK: [[STACK:%.*]] = alloc_stack $MultipleFieldStruct
95+
// CHECK: [[MULTIPLE_FIELD_SEA:%.*]] = struct_element_addr [[STACK]]
96+
// CHECK: store [[ARG]] to [init] [[MULTIPLE_FIELD_SEA]]
97+
// CHECK: dealloc_stack [[STACK]]
98+
// CHECK: } // end sil function 'perform_no_work_if_multiple_fields'
99+
sil [ossa] @perform_no_work_if_multiple_fields : $@convention(thin) (@owned RecursiveSingleEltStructField, @owned Klass) -> () {
100+
bb0(%0 : @owned $RecursiveSingleEltStructField, %0a : @owned $Klass):
101+
%1 = alloc_stack $MultipleFieldStruct
102+
%2 = struct_element_addr %1 : $*MultipleFieldStruct, #MultipleFieldStruct.field
103+
%2a = struct_element_addr %1 : $*MultipleFieldStruct, #MultipleFieldStruct.k
104+
store %0a to [init] %2a : $*Klass
105+
store %0 to [init] %2 : $*RecursiveSingleEltStructField
106+
destroy_addr %1 : $*MultipleFieldStruct
107+
dealloc_stack %1 : $*MultipleFieldStruct
108+
%9999 = tuple()
109+
return %9999 : $()
110+
}
111+
112+
// CHECK-LABEL: sil [ossa] @only_promote_while_we_have_sea : $@convention(thin) (@owned Klass) -> () {
113+
// CHECK: bb0([[ARG:%.*]] :
114+
// CHECK: [[STACK:%.*]] = alloc_stack $(Klass, RecursiveSingleEltStructField)
115+
// CHECK: [[TUPLE_ADDR:%.*]] = tuple_element_addr [[STACK]]
116+
// CHECK: [[VALUE:%.*]] = struct $RecursiveSingleEltStructField ([[ARG]] : $Klass)
117+
// CHECK: store [[VALUE]] to [init] [[TUPLE_ADDR]]
118+
// CHECK: dealloc_stack [[STACK]]
119+
// CHECK: } // end sil function 'only_promote_while_we_have_sea'
120+
sil [ossa] @only_promote_while_we_have_sea : $@convention(thin) (@owned Klass) -> () {
121+
bb0(%0 : @owned $Klass):
122+
%1 = alloc_stack $(Klass, RecursiveSingleEltStructField)
123+
%2 = tuple_element_addr %1 : $*(Klass, RecursiveSingleEltStructField), 1
124+
%2a = tuple_element_addr %1 : $*(Klass, RecursiveSingleEltStructField), 0
125+
%0a = copy_value %0 : $Klass
126+
store %0a to [init] %2a : $*Klass
127+
%3 = struct_element_addr %2 : $*RecursiveSingleEltStructField, #RecursiveSingleEltStructField.k
128+
store %0 to [init] %3 : $*Klass
129+
destroy_addr %1 : $*(Klass, RecursiveSingleEltStructField)
130+
dealloc_stack %1 : $*(Klass, RecursiveSingleEltStructField)
131+
%9999 = tuple()
132+
return %9999 : $()
133+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
8+
class Foo {
9+
}
10+
11+
12+
sil @_TFC4main3Food : $@convention(method) (@owned Foo) -> @owned Builtin.NativeObject {
13+
bb0(%0 : $Foo):
14+
debug_value %0 : $Foo, let, name "self" // id: %1
15+
%2 = unchecked_ref_cast %0 : $Foo to $Builtin.NativeObject // user: %3
16+
return %2 : $Builtin.NativeObject // id: %3
17+
}
18+
19+
sil @_TFC4main3FooD : $@convention(method) (@owned Foo) -> () {
20+
bb0(%0 : $Foo):
21+
debug_value %0 : $Foo, let, name "self" // id: %1
22+
// function_ref main.Foo.deinit
23+
%2 = function_ref @_TFC4main3Food : $@convention(method) (@owned Foo) -> @owned Builtin.NativeObject // user: %3
24+
%3 = apply %2(%0) : $@convention(method) (@owned Foo) -> @owned Builtin.NativeObject // user: %4
25+
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $Foo // user: %5
26+
dealloc_ref %4 : $Foo // id: %5
27+
%6 = tuple () // user: %7
28+
return %6 : $() // id: %7
29+
}
30+
31+
sil @_TFC4main3FoocfMS0_FT_S0_ : $@convention(method) (@owned Foo) -> @owned Foo {
32+
bb0(%0 : $Foo):
33+
debug_value %0 : $Foo, let, name "self" // id: %1
34+
return %0 : $Foo // id: %2
35+
}
36+
37+
sil @_TFC4main3FooCfMS0_FT_S0_ : $@convention(thin) (@thick Foo.Type) -> @owned Foo {
38+
bb0(%0 : $@thick Foo.Type):
39+
%1 = alloc_ref $Foo // user: %3
40+
// function_ref main.Foo.init (main.Foo.Type)() -> main.Foo
41+
%2 = function_ref @_TFC4main3FoocfMS0_FT_S0_ : $@convention(method) (@owned Foo) -> @owned Foo // user: %3
42+
%3 = apply %2(%1) : $@convention(method) (@owned Foo) -> @owned Foo // user: %4
43+
return %3 : $Foo // id: %4
44+
}
45+
46+
sil [readonly] @_TF4main9readonly_funcFT_CS_3Foo : $@convention(thin) () -> @owned Foo {
47+
bb0:
48+
// function_ref main.Foo.__allocating_init (main.Foo.Type)() -> main.Foo
49+
%0 = function_ref @_TFC4main3FooCfMS0_FT_S0_ : $@convention(thin) (@thick Foo.Type) -> @owned Foo // user: %2
50+
%1 = metatype $@thick Foo.Type // user: %2
51+
%2 = apply %0(%1) : $@convention(thin) (@thick Foo.Type) -> @owned Foo // user: %3
52+
return %2 : $Foo // id: %3
53+
}
54+
55+
//CHECK-LABEL: @_TF4main3bazFT_T_
56+
//CHECK-NOT: function_ref
57+
//CHECK-NOT: apply
58+
//CHECK: tuple
59+
//CHECK-NEXT: return
60+
sil @_TF4main3bazFT_T_ : $@convention(thin) () -> () {
61+
bb0:
62+
// function_ref main.readonly_func () -> main.Foo
63+
%0 = function_ref @_TF4main9readonly_funcFT_CS_3Foo : $@convention(thin) () -> @owned Foo // user: %1
64+
%1 = apply %0() : $@convention(thin) () -> @owned Foo // users: %2, %3
65+
debug_value %1 : $Foo, let, name "unused" // id: %2
66+
strong_release %1 : $Foo // id: %3
67+
%4 = tuple () // user: %5
68+
return %4 : $() // id: %5
69+
}
70+
71+
sil_vtable Foo {
72+
#Foo.init!initializer: @_TFC4main3FoocfMS0_FT_S0_ // main.Foo.init (main.Foo.Type)() -> main.Foo
73+
}
74+
75+
76+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
8+
enum SimpleEnum {
9+
case Empty
10+
case HasInt(Int)
11+
case HasInt2(Int)
12+
}
13+
14+
//CHECK: _TF4main12test_union_1FT1EOS_10SimpleEnum_S0_
15+
//CHECK: switch_enum
16+
//CHECK: bb2
17+
//CHECK: enum $SimpleEnum, #SimpleEnum.HasInt2!enumelt, %{{[0-9]+}} : $Int
18+
//CHECK: bb3
19+
//CHECK: enum $SimpleEnum, #SimpleEnum.HasInt!enumelt, %{{[0-9]+}} : $Int
20+
//CHECK: bb4
21+
//CHECK: return
22+
23+
// main.test_union_1 (E : main.SimpleEnum) -> main.SimpleEnum
24+
sil [ossa] @_TF4main12test_union_1FT1EOS_10SimpleEnum_S0_ : $@convention(thin) (SimpleEnum) -> SimpleEnum {
25+
bb0(%0 : $SimpleEnum):
26+
%1 = alloc_stack $SimpleEnum, var, name "E" // users: %16, %2
27+
store %0 to [trivial] %1 : $*SimpleEnum // id: %2
28+
%3 = tuple ()
29+
switch_enum %0 : $SimpleEnum, case #SimpleEnum.Empty!enumelt: bb1, case #SimpleEnum.HasInt!enumelt: bb3, case #SimpleEnum.HasInt2!enumelt:bb4 // id: %4
30+
31+
bb1: // Preds: bb0
32+
%6 = enum $SimpleEnum, #SimpleEnum.Empty!enumelt // user: %7
33+
br bb5(%6 : $SimpleEnum) // id: %7
34+
35+
bb3(%8 : $Int): // Preds: bb0
36+
%9 = alloc_stack $Int, var, name "N" // users: %13, %10
37+
store %8 to [trivial] %9 : $*Int // id: %10
38+
%12 = enum $SimpleEnum, #SimpleEnum.HasInt2!enumelt, %8 : $Int // user: %14
39+
dealloc_stack %9 : $*Int // id: %13
40+
br bb5(%12 : $SimpleEnum) // id: %14
41+
42+
bb4(%13 : $Int): // Preds: bb0
43+
%14 = alloc_stack $Int, var, name "N" // users: %13, %10
44+
store %13 to [trivial] %14 : $*Int // id: %10
45+
%15 = enum $SimpleEnum, #SimpleEnum.HasInt!enumelt, %13 : $Int // user: %14
46+
dealloc_stack %14 : $*Int // id: %13
47+
br bb5(%15 : $SimpleEnum) // id: %14
48+
49+
bb5(%16 : $SimpleEnum): // Preds: bb2 bb4
50+
dealloc_stack %1 : $*SimpleEnum // id: %16
51+
return %16 : $SimpleEnum // id: %17
52+
}
53+

0 commit comments

Comments
 (0)