> On Oct 11, 2016, at 11:02 AM, Joe Groff <jgr...@apple.com> wrote: > > >> On Oct 11, 2016, at 10:50 AM, John McCall <rjmcc...@apple.com> wrote: >> >>> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev <swift-dev@swift.org> >>> 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. >> >> As I've pointed out in the past, this doesn't make any semantic sense. >> Projecting out a buffer reference as a true r-value creates an independent >> value and therefore requires bumping the reference count. The only query >> that makes semantic sense is "does this value hold a unique reference to its >> buffer", which requires some sort of language tool for talking abstractly >> about values without creating new, independent values. Our only existing >> language tool for that is inout, which allows you to talk about the value >> stored in a specific mutable variable. Ownership will give us a second and >> more general tool, borrowing, which allows you abstractly refer to immutable >> existing values. > > If we have @owned values, then we also have the ability to do a uniqueness > check on that value, don't we? This would necessarily consume the value, but > we could conditionally produce a new known-unique value on the path where the > uniqueness check succeeds. > > entry(%1: @owned $X): > is_uniquely_referenced %1, yes, no > yes(%2: /*unique*/ @owned $X): > // %2 is unique, until copied at least > no(%3: @owned %X): > // %3 is not > > -Joe
You had to copy $X to make it @owned. You could check uniqueness of @borrowed $X, but then you’d need to copy to create a new array (mutation) before destroying the original that you borrowed from. -Andy _______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev