> On Oct 11, 2016, at 10:33 AM, Andrew Trick <atr...@apple.com> wrote: > > >> On Oct 11, 2016, at 10:10 AM, Joe Groff <jgr...@apple.com> wrote: >> >> >>> On Oct 10, 2016, at 6:58 PM, Andrew Trick <atr...@apple.com> wrote: >>> >>> >>>> On Oct 10, 2016, at 6:23 PM, Joe Groff <jgr...@apple.com> wrote: >>>> >>>> >>>>> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev >>>>> <swift-dev@swift.org> wrote: >>>>> ** World 1: SSA @inout >>>>> >>>>> Projecting an element produces a new SILValue. Does this SILValue have >>>>> it's own ownership associated with it's lifetime, or is it derived >>>>> from it's parent object by looking through projections? >>>>> >>>>> Either way, projecting any subelement requires reconstructing the >>>>> entire aggregate in SIL, through all nesting levels. This will >>>>> generate a massive amount of SILValues. Superficially they all need >>>>> their own storage. >>>>> >>>>> [We could claim that projections don't need storage, but that only >>>>> solves one side of the problem.] >>>>> >>>>> [I argue that this actually obscures the producer/consumer >>>>> relationship, which is the opposite of the intention of moving to >>>>> SSA. Projecting subelements for mutation fundamentally doesn't make >>>>> sense. It does make sense to borrow a subelement (not for >>>>> mutation). It also makes sense to project a mutable storage >>>>> location. The natural way to project a storage location is by >>>>> projecting an address...] >>>> >>>> I think there's a size threshold at which SSA @inout is manageable, and >>>> might lead to overall better register-oriented code, if the aggregates can >>>> be exploded into a small number of individual values. The cost of >>>> reconstructing the aggregate could be mitigated somewhat by introducing >>>> 'insert' instructions for aggregates to pair with the projection >>>> instructions, similar to how LLVM has insert/extractelement. "%x = >>>> project_value %y.field; %x' = transform(%x); %y' = insert %y.field, %x" >>>> isn't too terrible compared to the address-oriented formulation. Tracking >>>> ownership state through projections and insertions might tricky; haven't >>>> thought about that aspect. >>>> >>>> -Joe >>> >>> We would have to make sure SROA+mem2reg could still kick in. If that >>> happens, I don’t think we need to worry about inout ownership semantics >>> anymore. A struct_extract is then essentially a borrow. It’s parent’s >>> lifetime needs to be guaranteed, but I don’t know if the subobject needs >>> explicit scoping in SIL since there’s no inout scopes to worry about and >>> nothing for the runtime to do when the scope ends . >>> >>> (Incidentally, this would never happen to a CoW type that has a uniqueness >>> check—to mutate a CoW type, it’s value needs to be in memory). >> >> Does a uniqueness check still need to be associated with a memory location >> once we associate ownership with SSA values? It seems to me like it wouldn't >> necessarily need to be. One thing I'd like us to work toward is being able >> to reliably apply uniqueness checks to rvalues, so that code in a "pure >> functional" style gets the same optimization benefits as code that >> explicitly uses inouts. >> >> -Joe > > We could have an is_unique instruction that returns a “new” reference to > storage. But our model for CoW data types relies mutating methods so I don't > really know what you have in mind.
It doesn't fundamentally have to be tied to mutating methods. After all, you ought to be able to take a value parameter you received as uniquely-referenced, and work on that in-place: func appendTwoArrays(a: [Int], b: [Int]) -> [Int] { var a2 = __move__ a // fake syntax to force a move of ownership if isUniquelyReferenced(&a2) { a2.buffer._appendInPlace(b.buffer) } else { a2.buffer = Array(buffer: ArrayBuffer(appending: a2.buffer, and: b.buffer) } return a2 } -Joe _______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev