Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-14116] Differentiation: class property modify accessor applications are not active #54685

Open
Tracked by #54401 ...
dan-zheng opened this issue Feb 23, 2020 · 2 comments
Labels
AutoDiff bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@dan-zheng
Copy link
Collaborator

Previous ID SR-14116
Radar None
Original Reporter @dan-zheng
Type Sub-task
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Sub-task, AutoDiff
Assignee None
Priority Medium

md5: 52c4e7292d358396a625c0c7b20dc52c

Parent-Task:

  • SR-14113 Support _read and _modify accessor differentiation

Issue Description:

class Class: Differentiable {
  @differentiable
  var x: Float

  init(_ x: Float) {
    self.x = x
  }
}

@_silgen_name("inout_mutating")
func inoutMutating(_ c: inout Class) {
  c.x *= c.x
}
func squared(_ x: Float) -> Float {
  var c = Class(x)
  inoutMutating(&c)
  return c.x
}
print(valueWithGradient(at: 10, in: squared))
//   Actual: (value: 100.0, gradient: 1.0)
// Expected: (value: 100.0, gradient: 20.0)

The issue is in inoutMutating, which calls Class.x.modify. The modify accessor application is not active:

[AD] Activity info for inout_mutating at (source=0 parameters=(0))
bb0:
[ACTIVE] %0 = argument of bb0 : $*Class                    // users: %6, %3, %1
[NONE]   %2 = metatype $@thin Float.Type                 // user: %19
[ACTIVE]   %3 = begin_access [read] [static] %0 : $*Class  // users: %5, %4
[VARIED]   %4 = load [copy] %3 : $*Class                   // users: %22, %14
[ACTIVE]   %6 = begin_access [read] [static] %0 : $*Class  // users: %8, %7
[VARIED]   %7 = load [copy] %6 : $*Class                   // users: %13, %9
[VARIED]   %9 = begin_borrow %7 : $Class                   // users: %12, %11, %10
[VARIED]   %10 = class_method %9 : $Class, #Class.x!getter.1 : (Class) -> () -> Float, $@convention(method) (@guaranteed Class) -> Float // user: %11
[VARIED]   %11 = apply %10(%9) : $@convention(method) (@guaranteed Class) -> Float // user: %19
[VARIED]   %14 = begin_borrow %4 : $Class                  // users: %21, %16, %15
[VARIED]   %15 = class_method %14 : $Class, #Class.x!modify.1 : (Class) -> () -> (), $@yield_once @convention(method) (@guaranteed Class) -> @yields @inout Float // user: %16
[VARIED] (**%16**, %17) = begin_apply %15(%14) : $@yield_once @convention(method) (@guaranteed Class) -> @yields @inout Float // user: %19
[VARIED] (%16, **%17**) = begin_apply %15(%14) : $@yield_once @convention(method) (@guaranteed Class) -> @yields @inout Float // user: %20
[NONE]   // function_ref static Float.*= infix(_:_:)
  %18 = function_ref @$sSf2meoiyySfz_SftFZ : $@convention(method) (@inout Float, Float, @thin Float.Type) -> () // user: %19
[NONE]   %19 = apply %18(%16, %11, %2) : $@convention(method) (@inout Float, Float, @thin Float.Type) -> ()
[NONE]   %23 = tuple ()                                  // user: %24
@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@asl
Copy link
Collaborator

asl commented Apr 7, 2023

Our activity analysis is just plain wrong for class arguments. In particular, the usefullness analysis is not quite prepared for such values. Currently the inouts are treated in such a way, that the argument is marked as a result and usefullness is propagated backwards from results to instruction operands. This works for usual inouts and even for struct self arguments simply because there is a "last store" to inout argument that allows usefulness to propagate back. This is not quite so in case of classes. And it could be seen even in a simple case with just plain setter call:

@_silgen_name("inout_setting")
func inoutSetting(_ c: inout Class, x : Float) {
  c.x = x
}

func foo(_ x: Float) -> Float {
  var c = Class(x)
  inoutSetting(&c, x: x)
  return c.x
}

yeilds:

[AD] Activity info for inout_setting at parameter indices (0, 1) and result indices (0):
bb0:
[ACTIVE] %0 = argument of bb0 : $*Class                    // users: %4, %2
[VARIED] %1 = argument of bb0 : $Float                     // users: %8, %3
[ACTIVE]   %4 = begin_access [read] [static] %0 : $*Class  // users: %6, %5
[VARIED]   %5 = load [copy] %4 : $*Class                   // users: %9, %8, %7
[VARIED]   %7 = class_method %5 : $Class, #Class.x!setter : (Class) -> (Float) -> (), $@convention(method) (Float, @guaranteed Class) -> () // user: %8
[NONE]   %8 = apply %7(%1, %5) : $@convention(method) (Float, @guaranteed Class) -> ()
[NONE]   %10 = tuple ()                                  // user: %11
End activity info for inout_setting

There is a special case in usefullness calculation (propagateUsefulThroughAddress) that makes %4 active here (essentially for addresses and class-valued arguments we propagate useful similar to how we're propagating varied – looking into users, but this is only done for projections, this is why %5 is not marked as active here).

@asl
Copy link
Collaborator

asl commented Apr 7, 2023

Tagging @rxwei @BradLarson

@AnthonyLatsis AnthonyLatsis added the bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. label Apr 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
AutoDiff bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

3 participants