Commits
Chris Lattner committed c6a334ab6e8
teach SILGenFunction::emitLoad that clients allowing +0 results don't
need the load (and temporary, and cleanup) to actually be emitted for
address-only operands. They can just use the physical lvalue as the +0 base.
In this example:
struct GenericStruct<T> {
var a : T
var b : Int
func getA() -> T {
return a
}
func getB() -> Int {
return b
}
}
we used to produce:
sil @_TFV2t213GenericStruct4getAU__fGS0_Q__FT_Q_ : $@cc(method) @thin <$T_0_0> (@out $T_0_0, @in GenericStruct<$T_0_0>) -> () {
bb0(%0 : $*T, %1 : $*GenericStruct<T>):
debug_value_addr %1 : $*GenericStruct<T> // let self // id: %2
%3 = alloc_stack $GenericStruct<T> // users: %8, %7, %5, %4
copy_addr %1 to [initialization] %3#1 : $*GenericStruct<T> // id: %4
%5 = struct_element_addr %3#1 : $*GenericStruct<T>, #a // user: %6
copy_addr %5 to [initialization] %0 : $*T // id: %6
destroy_addr %3#1 : $*GenericStruct<T> // id: %7
dealloc_stack %3#0 : $*@local_storage GenericStruct<T> // id: %8
destroy_addr %1 : $*GenericStruct<T> // id: %9
%10 = tuple () // user: %11
return %10 : $() // id: %11
}
sil @_TFV2t213GenericStruct4getBU__fGS0_Q__FT_Si : $@cc(method) @thin <$T_0_0> (@in GenericStruct<$T_0_0>) -> Int64 {
bb0(%0 : $*GenericStruct<T>):
debug_value_addr %0 : $*GenericStruct<T> // let self // id: %1
%2 = alloc_stack $GenericStruct<T> // users: %7, %6, %4, %3
copy_addr %0 to [initialization] %2#1 : $*GenericStruct<T> // id: %3
%4 = struct_element_addr %2#1 : $*GenericStruct<T>, #b // user: %5
%5 = load %4 : $*Int64 // user: %9
destroy_addr %2#1 : $*GenericStruct<T> // id: %6
dealloc_stack %2#0 : $*@local_storage GenericStruct<T> // id: %7
destroy_addr %0 : $*GenericStruct<T> // id: %8
return %5 : $Int64 // id: %9
}
now we produce:
sil @_TFV2t213GenericStruct4getAU__fGS0_Q__FT_Q_ : $@cc(method) @thin <$T_0_0> (@out $T_0_0, @in GenericStruct<$T_0_0>) -> () {
bb0(%0 : $*T, %1 : $*GenericStruct<T>):
debug_value_addr %1 : $*GenericStruct<T> // let self // id: %2
%3 = struct_element_addr %1 : $*GenericStruct<T>, #a // user: %4
copy_addr %3 to [initialization] %0 : $*T // id: %4
destroy_addr %1 : $*GenericStruct<T> // id: %5
%6 = tuple () // user: %7
return %6 : $() // id: %7
}
sil @_TFV2t213GenericStruct4getBU__fGS0_Q__FT_Si : $@cc(method) @thin <$T_0_0> (@in GenericStruct<$T_0_0>) -> Int64 {
bb0(%0 : $*GenericStruct<T>):
debug_value_addr %0 : $*GenericStruct<T> // let self // id: %1
%2 = struct_element_addr %0 : $*GenericStruct<T>, #b // user: %3
%3 = load %2 : $*Int64 // user: %5
destroy_addr %0 : $*GenericStruct<T> // id: %4
return %3 : $Int64 // id: %5
}
This cuts about 120 lines out of the stdlib (so, about 40 temporaries).
Swift SVN r12871