Skip to content

[AutoDiff] Refine debug info emitted for adjoint buffers #62779

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

Merged
merged 4 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/SILOptimizer/Differentiation/PullbackCloner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,23 @@ class PullbackCloner::Implementation final
auto debugInfo = findDebugLocationAndVariable(originalValue);
SILLocation loc = debugInfo ? debugInfo->first.getLocation()
: RegularLocation::getAutoGeneratedLocation();
llvm::SmallString<32> adjName;
auto *newBuf = createFunctionLocalAllocation(
bufType, loc, /*zeroInitialize*/ true,
debugInfo.transform([](AdjointValue::DebugInfo di) { return di.second; }));
debugInfo.transform(
[&](AdjointValue::DebugInfo di) {
llvm::raw_svector_ostream adjNameStream(adjName);
SILDebugVariable &dv = di.second;
dv.ArgNo = 0;
adjNameStream << "derivative of '" << dv.Name << "'";
if (SILDebugLocation origBBLoc = origBB->front().getDebugLocation()) {
adjNameStream << " in scope at ";
origBBLoc.getLocation().print(adjNameStream, getASTContext().SourceMgr);
}
adjNameStream << " (scope #" << origBB->getDebugID() << ")";
dv.Name = adjName;
return dv;
}));
return (insertion.first->getSecond() = newBuf);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %target-build-swift %s
// RUN: %target-swift-frontend -emit-sil -O -g %s | %FileCheck %s

// REQUIRES: swift_in_compiler

// Issue #58660: Specifically-shaped differentiable functions yield "conflicting debug info for argument" assertion failure
// Ensure that proper location is preserved after sil-mem2reg location-less stores (created during inlining)

Expand Down Expand Up @@ -42,9 +44,9 @@ struct MyModel: Differentiable {
@differentiable(reverse)
mutating func member4() {
// CHECK-LABEL: // pullback of MyModel.member4()
// CHECK-NOT: debug_value %{{.*}} : $MyModel.TangentVector, var, name "self", argno 1, implicit, scope
// CHECK-NOT: debug_value %{{.*}} : $MyModel.TangentVector, var, name %{{.*}}, argno 1, implicit, scope
// CHECK: bb1(%{{.*}} : $_AD__$s4main7MyModelV7member4yyF_bb1__PB__src_0_wrt_0):
// CHECK: debug_value %{{.*}} : $MyModel.TangentVector, var, name "self", argno 1, implicit, loc
// CHECK: debug_value %{{.*}} : $MyModel.TangentVector, var, name "derivative of 'self' in scope at {{.*}} (scope #1)", implicit, scope
// Must be a differentiable type.
var localVar: Float = 0

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// RUN: %target-swift-frontend -emit-sil -O -g %s | %FileCheck %s

// REQUIRES: swift_in_compiler
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this require swift_in_compiler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is optimized on Windows differently due to lack of optimization passes written in Swift....


// Fix for https://github.com/apple/swift/issues/62608
// We need to emit separate debug info location for different adjoint buffers
// created for the single input variable

import _Differentiation

public extension Array {
@inlinable
@differentiable(reverse)
mutating func update(at index: Int, byCalling closure: @differentiable(reverse) (inout Element) -> Void) where Element: Differentiable {
closure(&self[index])
}
}

public func valueWithPullback<T>(
at x: T, of f: @differentiable(reverse) (inout T) -> Void
) -> (value: Void, pullback: (inout T.TangentVector) -> Void) {
@differentiable(reverse)
func nonInoutWrappingFunction(_ t: T) -> T {
var t = t
f(&t)
return t
}
let nonInoutPullback = pullback(at: x, of: nonInoutWrappingFunction)
return ((), { $0 = nonInoutPullback($0) })
}

@inlinable
public func pullback<T>(
at x: T, of f: @differentiable(reverse) (inout T) -> Void
) -> (inout T.TangentVector) -> Void {
return valueWithPullback(at: x, of: f).pullback
}

// CHECK-LABEL: sil private @$s4main19testUpdateByCallingyyKF8fOfArrayL_5arraySdSaySdG_tFySdzcfU_TJpSUpSr :
// CHECK: alloc_stack $Double, var, name "derivative of 'element' in scope at {{.*}} (scope #3)"
// CHECK: debug_value %{{.*}} : $Builtin.FPIEEE64, var, (name "derivative of 'element' in scope at {{.*}} (scope #1)"

public extension Array where Element: Differentiable {
@inlinable
@derivative(of: update(at:byCalling:))
mutating func vjpUpdate(
at index: Int,
byCalling closure: @differentiable(reverse) (inout Element) -> Void
)
->
(value: Void, pullback: (inout Self.TangentVector) -> Void)
{
let closurePullback = pullback(at: self[index], of: closure)
return (value: (), pullback: { closurePullback(&$0.base[index]) })
}
}

func testUpdateByCalling() throws {
@differentiable(reverse)
func fOfArray(array: [Double]) -> Double {
var array = array
var result = 0.0
for i in withoutDerivative(at: 0 ..< array.count) {
array.update(at: i, byCalling: { (element: inout Double) in
let initialElement = element
for _ in withoutDerivative(at: 0 ..< i) {
element *= initialElement
}
})
result += array[i]
}
return result
}

let array = [Double](repeating: 1.0, count: 3)
let expectedGradientOfFOfArray = [1.0, 2.0, 3.0]
let obtainedGradientOfFOfArray = gradient(at: array, of: fOfArray).base
}