Commits

Chris Lattner committed 373d0de7660
Now that SILGen is in charge of temporary materialization (or not) we can implement fun optimizations. Here, we avoid materializing a temporary copy for 'let' bases of protocol and archetype methods. Consider: protocol SimpleProtocol { func doSomethingGreat() } func testLetProtocolBases(let p : SimpleProtocol) { p.doSomethingGreat() p.doSomethingGreat() } before we produced: sil @_TF1t20testLetProtocolBasesFT1pPS_14SimpleProtocol__T_ : $@thin (@in SimpleProtocol) -> () { bb0(%0 : $*SimpleProtocol): %1 = alloc_stack $SimpleProtocol // users: %7, %6, %4, %3, %2 copy_addr %0 to [initialization] %1#1 : $*SimpleProtocol // id: %2 %3 = project_existential %1#1 : $*SimpleProtocol to $*@sil_self SimpleProtocol // user: %5 %4 = protocol_method %1#1 : $*SimpleProtocol, #SimpleProtocol.doSomethingGreat!1 : $@cc(witness_method) @callee_owned (@inout Self) -> () // user: %5 %5 = apply %4(%3) : $@cc(witness_method) @callee_owned (@inout Self) -> () destroy_addr %1#1 : $*SimpleProtocol // id: %6 dealloc_stack %1#0 : $*@local_storage SimpleProtocol // id: %7 %8 = alloc_stack $SimpleProtocol // users: %14, %13, %11, %10, %9 copy_addr %0 to [initialization] %8#1 : $*SimpleProtocol // id: %9 %10 = project_existential %8#1 : $*SimpleProtocol to $*@sil_self SimpleProtocol // user: %12 %11 = protocol_method %8#1 : $*SimpleProtocol, #SimpleProtocol.doSomethingGreat!1 : $@cc(witness_method) @callee_owned (@inout Self) -> () // user: %12 %12 = apply %11(%10) : $@cc(witness_method) @callee_owned (@inout Self) -> () destroy_addr %8#1 : $*SimpleProtocol // id: %13 dealloc_stack %8#0 : $*@local_storage SimpleProtocol // id: %14 destroy_addr %0 : $*SimpleProtocol // id: %15 %16 = tuple () // user: %17 return %16 : $() // id: %17 } now we produce the svelte: sil @_TF1t20testLetProtocolBasesFT1pPS_14SimpleProtocol__T_ : $@thin (@in SimpleProtocol) -> () { bb0(%0 : $*SimpleProtocol): %1 = project_existential %0 : $*SimpleProtocol to $*@sil_self SimpleProtocol // user: %3 %2 = protocol_method %0 : $*SimpleProtocol, #SimpleProtocol.doSomethingGreat!1 : $@cc(witness_method) @callee_owned (@inout Self) -> () // user: %3 %3 = apply %2(%1) : $@cc(witness_method) @callee_owned (@inout Self) -> () %4 = project_existential %0 : $*SimpleProtocol to $*@sil_self SimpleProtocol // user: %6 %5 = protocol_method %0 : $*SimpleProtocol, #SimpleProtocol.doSomethingGreat!1 : $@cc(witness_method) @callee_owned (@inout Self) -> () // user: %6 %6 = apply %5(%4) : $@cc(witness_method) @callee_owned (@inout Self) -> () destroy_addr %0 : $*SimpleProtocol // id: %7 %8 = tuple () // user: %9 return %8 : $() // id: %9 } It turns out that 'var's were getting this optimization accidentally because the var box had the single reference, but that it didn't work for 'let's. It turns out that this optimization matters a lot when you enter the intersection of "required optimizations" that our string/array append implementation imply: doing the extra copy defeats their "has one reference" optimizations. This also refactors some code into a shared place between archetypes and existentials. Swift SVN r12131