Re: [swift-dev] Validating ABI consistency between runtime C++ and standard library Swift code

2016-10-11 Thread Daniel Dunbar via swift-dev
Can you directly pass arguments to the function crossing the ABI boundary, and 
can you directly access them on the other side? If so, what you can do is 
simply synthesize arguments that cross the full range of the bit-representation 
of the argument types, and validate that you see the same range on the other 
side.

I don't know anything about what this interface looks like so I don't have more 
specific ideas, but if you can give me a little more context I've worked on 
this in the past...

Technically you can't necessarily compare the LLVM IR, since there are ways to 
represent the same ABI call with different #s of IR arguments in corner cases.

 - Daniel

> On Oct 11, 2016, at 8:10 PM, Joe Groff via swift-dev  
> wrote:
> 
> I just tracked down a bug due to C++ code in the Swift runtime code trying to 
> interface with standard library code written in Swift, but getting the ABI 
> slightly wrong and leading to some nasty hard-to-reproduce heisenbugs. While 
> I've narrowed down the bug in this specific case, it seems like this is a 
> potentially continuing source of maintenance bugs, especially as we try to 
> bring up the Swift calling convention in the coming year. I'm wondering if 
> there's anything we could do to help validate that C++ and Swift code in the 
> runtime is correctly interfacing. We could at least check that we're passing 
> the right number of arguments by comparing the LLVM IR of the runtime and 
> stdlib, perhaps, though this would have to be a fuzzy type-level match since 
> Clang and Swift aren't normally going to agree on the exact pointer types of 
> arguments.
> 
> -Joe
> ___
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


[swift-dev] Validating ABI consistency between runtime C++ and standard library Swift code

2016-10-11 Thread Joe Groff via swift-dev
I just tracked down a bug due to C++ code in the Swift runtime code trying to 
interface with standard library code written in Swift, but getting the ABI 
slightly wrong and leading to some nasty hard-to-reproduce heisenbugs. While 
I've narrowed down the bug in this specific case, it seems like this is a 
potentially continuing source of maintenance bugs, especially as we try to 
bring up the Swift calling convention in the coming year. I'm wondering if 
there's anything we could do to help validate that C++ and Swift code in the 
runtime is correctly interfacing. We could at least check that we're passing 
the right number of arguments by comparing the LLVM IR of the runtime and 
stdlib, perhaps, though this would have to be a fuzzy type-level match since 
Clang and Swift aren't normally going to agree on the exact pointer types of 
arguments.

-Joe
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] copy-on-write proposal

2016-10-11 Thread Michael Gottesman via swift-dev
> 
> 
> :orphan:
> 
> .. highlight:: sil
> 
> ===
> Copy-On-Write Representation in SIL
> ===
> 
> .. contents::
> 
> Overview
> 
> 
> This document proposes:
> 
> - An ownership attribute to define copy-on-write (COW) buffers in Swift data
>   types.
> 
> - A representation of COW buffers in SIL so that optimizations can take 
> benefit
>   of it.
> 
> The basic idea is to enable the SIL optimizer to reason about COW data types
> in the same way as a programmer can do.

in the same way as a programmer can do => just as a programmer can.

> 
> 
> This means: a COW buffer can only be modified by its owning SIL value, because
> either it's uniquely referenced or the buffer is copied before modified.

modified => modification.

> 
> .. note::
> In the following the term "buffer" refers to a Swift heap object.
> It can be any heap object, not necessarily a “buffer” with e.g. 
> tail-allocated elements.
> 
> COW Types
> =
> 
> The basic structure of COW data types can be simplified as follows::
> 
> class COWBuffer {
>   var someData: Int
>   ...
> }
> 
> struct COWType {
>   var b : COWBuffer
> 
>   mutating func change_it() {
> if (!isUniquelyReferenced(b)) {
>   b = copy_buffer(b)
> }
> b.someData = ...
>   }
> }
> 
> Currently the COW behavior of such types is just defined by their 
> implementation.
> But there is no representation of this special behavior in the SIL.
> So the SIL optimizer has no clue about it and cannot take advantage of it.
> 
> For example::
> 
> func foo(arr : [Int]) {
>   x = arr[0]
>   opaque_function()
>   y = arr[0] // can RLE replace this with y = x?
> }
> 
> If opaque_function() wants to change the contents of the array buffer it first
> has to copy it. But the optimizer does not know it so it has to conservatively
> assume that opaque_function() will write to the location of arr[0].
> 
> Copy-on-write Ownership Attribute
> =
> 
> This section proposes an ownership attribute to define a copy-on-write buffer.
> 
> Swift Syntax
> 
> 
> A COW buffer reference can be defined with a new ownership attribute for the
> buffer variable declaration (similar to “weak” and “unowned”)::
> 
> struct COWType {
>   copy_on_write var b : COWBuffer
> 
>   // ...
> }
> 
> The ``copy_on_write`` attribute is purely used for optimization purposes.
> It does not change the semantics of the program.
> 
> .. note::
> 
>   “copy_on_write” is a  working title. TODO: decide on the name.
>   Maybe it should be a @-attribute, like @copy_on_write?
>   Another question is if we should open this attribute for the public or just
>   use it internally in the library, because violating the implied rules
>   (see below) could break memory safety.
> 
> Implementation
> --
> 
> The ``copy_on_write`` references can be represented in the AST as a special

"The" is not needed here I think.

> ``StorageType``, just like how ``unowned`` and ``weak`` is represented.

is represented => are represented.

> The canonical type of a ``CopyOnWriteStorageType`` would be the referenced
> buffer class type.
> 
> In SIL the buffer reference will have type::
> 
> $@sil_cow COWBuffer
> 
> where ``COWBuffer`` is the type of the referenced heap object.
> 
> Two conversion instructions are needed to convert from a ``@sil_cow`` 
> reference
> type to a regular reference type::
> 
> cow_to_ref
> ref_to_cow
>  
> Again, this is similar to ``ref_to_unowned`` and ``unowned_to_ref``.
> 
> For example the SIL code for::
> 
> var c: COWType
> let x = c.b.someData
> 
> would be::
> 
> %1 = struct_extract %1 : COWType, #COWType.b
> %2 = cow_to_ref %1 : $@sil_cow COWBuffer
> %3 = ref_element_addr %2 : $COWBuffer, #COWBuffer.someData
> %4 = load %3 : $*Int
> 
> The ``ref_to_cow`` instruction is needed to store a new buffer reference into 
> a
> COW type.
> 
> COW Buffers and the Optimizer
> =
> 
> A reference to a COW buffer gives the optimizer additional information:
> 
>   *A buffer, referenced by a @sil_cow reference is considered to be immutable
>   during the lifetime of the reference.*
> 
> This means any address derived from a ``cow_to_ref`` instruction can be
> considered to point to immutable memory.
> 
> Some examples of optimizations which will benefit from copy-on-write
> representation in SIL:
> 
> - Redundant load elimination
> 
>   RLE can assume that opaque code does not modify a COW buffer.
>   Example::
> 
>   %2 = cow_to_ref %1 : $@sil_cow COWBuffer
>   %3 = ref_element_addr %2 : $COWBuffer, #someData
>   %4 = load %3 : $*Int
>   %5 = apply %foo()// Cannot overwrite memory 
> location %3
>   %6 = load %3 : $*Int // Can be replaced by %4
> 
>   Currently we 

Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread John McCall via swift-dev
> On Oct 11, 2016, at 4:48 PM, Andrew Trick  wrote:
>> On Oct 11, 2016, at 2:14 PM, John McCall  wrote:
>> 
>>> On Oct 11, 2016, at 11:49 AM, Joe Groff  wrote:
 On Oct 11, 2016, at 11:44 AM, John McCall  wrote:
 
> On Oct 11, 2016, at 11:22 AM, Joe Groff  wrote:
>> On Oct 11, 2016, at 11:19 AM, Andrew Trick  wrote:
>> 
>> 
>>> On Oct 11, 2016, at 11:02 AM, Joe Groff  wrote:
>>> 
>>> 
 On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
 
> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev 
>  wrote:
>> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
>> 
>> 
>>> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
>>> 
>>> 
 On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
  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 

[swift-dev] Is SE-0138 UnsafeRawBufferPointer included in Xcode 8 beta 3?

2016-10-11 Thread Norio Nomura via swift-dev
The release notes of Xcode 8.1 beta 3 said:
> Two types have been added to the Swift standard library: 
> UnsafeRawBufferPointer
and UnsafeMutableRawBufferPointer.

But I'm getting errors on building sample codes in release notes:
```

*➜  **9:10:46 * DEVELOPER_DIR=/Applications/Xcode-beta.app swift

Welcome to Apple Swift version 3.0.1 (swiftlang-800.0.56 clang-800.0.42).
Type :help for assistance.

  1> struct Header {

  2. var x: Int

  3. var y: Float

  4. }

  5.

  6. var header = Header(x: 0, y: 0.0)

  7. var byteBuffer = [UInt8]()

  8. withUnsafeBytes(of: ) { (bytes: UnsafeRawBufferPointer) in

  9. byteBuffer += bytes

 10. }

 11.

 12. let intArray = [1, 2, 3]

 13.

 14. intArray.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in

 15. byteBuffer += bytes

 16. }

error: repl.swift:8:1: error: use of unresolved identifier 'withUnsafeBytes'

withUnsafeBytes(of: ) { (bytes: UnsafeRawBufferPointer) in

^~~


error: repl.swift:8:40: error: use of undeclared type
'UnsafeRawBufferPointer'

withUnsafeBytes(of: ) { (bytes: UnsafeRawBufferPointer) in

   ^~


error: repl.swift:14:36: error: use of undeclared type
'UnsafeRawBufferPointer'

intArray.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in

   ^~



  1>

```

Am I missing something needed for using them?
Thanks,

Norio Nomura @norio_nomura
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


[swift-dev] copy-on-write proposal

2016-10-11 Thread Erik Eckstein via swift-dev
This is a proposal for representing copy-on-write buffers in SIL. Actually it’s 
still a draft for a proposal. It also heavily depends on how we move forward 
with SIL ownership.


CopyOnWrite.rst
Description: Binary data

If you have any comments, please let me know.

Erik


___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Andrew Trick via swift-dev

> On Oct 11, 2016, at 2:14 PM, John McCall  wrote:
> 
>> On Oct 11, 2016, at 11:49 AM, Joe Groff  wrote:
>>> On Oct 11, 2016, at 11:44 AM, John McCall  wrote:
>>> 
 On Oct 11, 2016, at 11:22 AM, Joe Groff  wrote:
> On Oct 11, 2016, at 11:19 AM, Andrew Trick  wrote:
> 
> 
>> On Oct 11, 2016, at 11:02 AM, Joe Groff  wrote:
>> 
>> 
>>> On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
>>> 
 On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev 
  wrote:
> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
> 
> 
>> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
>> 
>> 
>>> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>>>  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 

Re: [swift-dev] CI outage tomorrow

2016-10-11 Thread mishal_shah via swift-dev
Update completed. 

Please download Xcode 8.1 beta 3 from https://developer.apple.com/download/

Thanks, 
Mishal Shah
> On Oct 11, 2016, at 2:14 PM, mishal_shah via swift-dev  
> wrote:
> 
> Reminder: 
> 
> Starting update right now. 
> 
> During the update, please don’t trigger pull request testing on GitHub. 
> 
> Thanks, 
> Mishal Shah
> 
>> On Oct 10, 2016, at 6:16 PM, Nicole Jacque via swift-dev 
>>  wrote:
>> 
>> Hi All-
>> 
>> The CI bots on swift.org will be down temporarily, starting at 2 PM 
>> (California time) while we install the newest Xcode beta.  We’ll post a 
>> corresponding preview snapshot at that time as well. 
>> 
>> Thanks!
>> Nicole
>> 
>> ___
>> swift-dev mailing list
>> swift-dev@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-dev
> 
> ___
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread John McCall via swift-dev
> On Oct 11, 2016, at 11:49 AM, Joe Groff  wrote:
>> On Oct 11, 2016, at 11:44 AM, John McCall  wrote:
>> 
>>> On Oct 11, 2016, at 11:22 AM, Joe Groff  wrote:
 On Oct 11, 2016, at 11:19 AM, Andrew Trick  wrote:
 
 
> On Oct 11, 2016, at 11:02 AM, Joe Groff  wrote:
> 
> 
>> On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
>> 
>>> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev 
>>>  wrote:
 On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
 
 
> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
> 
> 
>> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>>  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 

Re: [swift-dev] CI outage tomorrow

2016-10-11 Thread mishal_shah via swift-dev
Reminder: 

Starting update right now. 

During the update, please don’t trigger pull request testing on GitHub. 

Thanks, 
Mishal Shah

> On Oct 10, 2016, at 6:16 PM, Nicole Jacque via swift-dev 
>  wrote:
> 
> Hi All-
> 
> The CI bots on swift.org will be down temporarily, starting at 2 PM 
> (California time) while we install the newest Xcode beta.  We’ll post a 
> corresponding preview snapshot at that time as well. 
> 
> Thanks!
> Nicole
> 
> ___
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Joe Groff via swift-dev

> On Oct 11, 2016, at 11:44 AM, John McCall  wrote:
> 
>> On Oct 11, 2016, at 11:22 AM, Joe Groff  wrote:
>>> On Oct 11, 2016, at 11:19 AM, Andrew Trick  wrote:
>>> 
>>> 
 On Oct 11, 2016, at 11:02 AM, Joe Groff  wrote:
 
 
> On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
> 
>> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev 
>>  wrote:
>>> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
>>> 
>>> 
 On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
 
 
> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>  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):
 // 

Re: [swift-dev] [semantic-arc][proposal] High Level ARC Memory Operations

2016-10-11 Thread Chris Lattner via swift-dev
On Oct 11, 2016, at 10:10 AM, Michael Gottesman  wrote:
>> >If ARC Code Motion wishes to move the ARC semantics of ownership qualified 
>> >load, store instructions, it must now consider read/write effects. On the 
>> >other hand, it will be able to now not consider the side-effects of 
>> >destructors when moving retain/release operations.
>> 
>> Can you elaborate on what you mean by this?  Does this mean the ARC 
>> optimizer has additional freedom somehow to ignore side effects in deinits?  
>> What grants that ability?
> 
> Sorry for not being clear.
> 
> deinits in ARC are not sequenced with respect to memory operations in normal 
> control flow, but if ARC performs any code motion, we must ensure that memory 
> safety is respected. Such semantics are not new.
> 
> The main change here is that previously there were situations where we would 
> split up the load/retain in a load [copy] operation. Then if the right things 
> occured, we could cause the object to be deallocated before we use the value 
> or took full ownership of the value.

Ah, I see what you mean.  Got it.

> In this case, we would be passing off to useD a deallocated instance of class 
> D1 which would be undefined behavior.
> 
> So as long as for these load [copy] operations, we move the load/retain fused 
> together, we can guarantee that an object is produced instantaneously in a 
> safe way without any worry.
> 
> Was this helpful?

Yep, totally.  The new approach is much more clear, thanks Michael!

-Chris


___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Joe Groff via swift-dev

> On Oct 11, 2016, at 11:19 AM, Andrew Trick  wrote:
> 
> 
>> On Oct 11, 2016, at 11:02 AM, Joe Groff  wrote:
>> 
>> 
>>> On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
>>> 
 On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev 
  wrote:
> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
> 
> 
>> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
>> 
>> 
>>> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>>>  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.

This is the part I think I'm missing. It's not clear to me why this is the 
case, though. You could have had an Array return value that has never been 
stored in memory, so never needed to be copied. If you have an 

Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Andrew Trick via swift-dev

> On Oct 11, 2016, at 11:02 AM, Joe Groff  wrote:
> 
> 
>> On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
>> 
>>> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev  
>>> wrote:
 On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
 
 
> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
> 
> 
>> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>>  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


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Joe Groff via swift-dev

> On Oct 11, 2016, at 10:50 AM, John McCall  wrote:
> 
>> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev  
>> wrote:
>>> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
>>> 
>>> 
 On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
 
 
> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>  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
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread John McCall via swift-dev
> On Oct 11, 2016, at 10:10 AM, Joe Groff via swift-dev  
> wrote:
>> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
>> 
>> 
>>> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
>>> 
>>> 
 On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
  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.

My point is that this isn't a SIL representational problem, it's a semantic 
problem that's being correctly reflected in SIL.  The language tools which will 
allow us to fix the semantic problem will necessarily also need to be reflected 
correctly in SIL, and so there won't be a representational problem.

John.
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Joe Groff via swift-dev

> On Oct 11, 2016, at 10:33 AM, Andrew Trick  wrote:
> 
> 
>> On Oct 11, 2016, at 10:10 AM, Joe Groff  wrote:
>> 
>> 
>>> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
>>> 
>>> 
 On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
 
 
> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>  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.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


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Andrew Trick via swift-dev

> On Oct 11, 2016, at 10:10 AM, Joe Groff  wrote:
> 
> 
>> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
>> 
>> 
>>> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
>>> 
>>> 
 On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
  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.

-Andy
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [semantic-arc][proposal] High Level ARC Memory Operations

2016-10-11 Thread Michael Gottesman via swift-dev

> On Oct 10, 2016, at 8:05 PM, Chris Lattner  wrote:
> 
> 
>> On Oct 7, 2016, at 2:38 PM, Michael Gottesman via swift-dev 
>> > wrote:
>> 
>> Attached below is an updated version of the proposal. Again a rendered 
>> version is located at:
>> 
>> https://gottesmm.github.io/proposals/high-level-arc-memory-operations.html 
>> 
>> 
>> Michael
> 
> This looks great Michael, a couple of comments/questions:
> 
> typo: affects -> effects.
> 
> 
> >If ARC Code Motion wishes to move the ARC semantics of ownership qualified 
> >load, store instructions, it must now consider read/write effects. On the 
> >other hand, it will be able to now not consider the side-effects of 
> >destructors when moving retain/release operations.
> 
> Can you elaborate on what you mean by this?  Does this mean the ARC optimizer 
> has additional freedom somehow to ignore side effects in deinits?  What 
> grants that ability?

Sorry for not being clear.

deinits in ARC are not sequenced with respect to memory operations in normal 
control flow, but if ARC performs any code motion, we must ensure that memory 
safety is respected. Such semantics are not new.

The main change here is that previously there were situations where we would 
split up the load/retain in a load [copy] operation. Then if the right things 
occured, we could cause the object to be deallocated before we use the value or 
took full ownership of the value.

Consider the following example:


class D {}
class D1 : D {}
class D2 : D {}

var GLOBAL_D : D = D1()

class C { deinit { GLOBAL_D = D2 } }

func main() {
  let c = C()
  let d = GLOBAL_D
  useC(c)
  useD(d)
}

main()


Assume that useC does not directly in any way touch an instance of class D 
except via the destructor .

Since memory operations are not sequenced with respect to deinits, there are 
two correct programs here that the optimizer can produce: the original and the 
one where useC(c) and GLOBAL_D are swapped, i.e.:


func main() {
  let c = C()
  useC(c)
  let d = GLOBAL_D
  useD(d)
}


In the first program, d would be an instance of class D1. In the second, it 
would be an instance of class D2. Notice how in both programs though, no 
deinitialized object is accessed. On the other hand, imagine if we had split 
main like so:


func main() {
  let c = C()
  let d = unsafe_unowned_load(GLOBAL_D)
  useC(c)
  let owned_d = retain(d)
  useD(owned_d)
}


In this case, we would be passing off to useD a deallocated instance of class 
D1 which would be undefined behavior.

So as long as for these load [copy] operations, we move the load/retain fused 
together, we can guarantee that an object is produced instantaneously in a safe 
way without any worry.

Was this helpful?
Michael

> 
> -Chris

___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


Re: [swift-dev] [discussion notes] SIL address types and borrowing

2016-10-11 Thread Joe Groff via swift-dev

> On Oct 10, 2016, at 6:58 PM, Andrew Trick  wrote:
> 
> 
>> On Oct 10, 2016, at 6:23 PM, Joe Groff  wrote:
>> 
>> 
>>> On Oct 7, 2016, at 11:10 PM, Andrew Trick via swift-dev 
>>>  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
___
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev