From 78f5e7e0a1e642f9d71eb48b3de65a6f78623ba5 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 4 Feb 2020 15:04:57 -0800 Subject: [PATCH] [AutoDiff] Fix `@noDerivative` attributes in non-primary-files. Previously, `@noDerivative` attribute type-checking generated implicit `@_semantics("autodiff.nonvarying")` attributes. However, attributes in non-primary-files are not type-checked, so `@noDerivative` attributes in non-primary-files are not processed. Now, all `@noDerivative` attributes are lowered to `[_semantics "autodiff.nonvarying"]` SIL function attributes. Resolves TF-1145. --- lib/SIL/SILFunctionBuilder.cpp | 9 +++++++++ lib/Sema/TypeCheckAttr.cpp | 13 +------------ .../Inputs/noderivative_attr_other_file.swift | 5 +++++ .../downstream/derived_differentiable.swift | 6 +++--- test/AutoDiff/downstream/noderivative_attr.swift | 10 +++++----- .../downstream/noderivative_attr_cross_file.swift | 8 ++++++++ 6 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 test/AutoDiff/downstream/Inputs/noderivative_attr_other_file.swift create mode 100644 test/AutoDiff/downstream/noderivative_attr_cross_file.swift diff --git a/lib/SIL/SILFunctionBuilder.cpp b/lib/SIL/SILFunctionBuilder.cpp index ed35dddacec3d..4c37a4c2ebac3 100644 --- a/lib/SIL/SILFunctionBuilder.cpp +++ b/lib/SIL/SILFunctionBuilder.cpp @@ -79,6 +79,15 @@ void SILFunctionBuilder::addFunctionAttributes(SILFunction *F, for (auto *A : Attrs.getAttributes()) (void)A->getParameterIndices(); + // Propagate `@noDerivative` as `[_semantics "autodiff.nonvarying"]`. + // + // `@noDerivative` implies non-varying semantics for differentiable activity + // analysis. SIL values produced from references to `@noDerivative` + // declarations will not be marked as varying; these values do not need a + // derivative. + if (Attrs.hasAttribute()) + F->addSemanticsAttr("autodiff.nonvarying"); + // Propagate @_dynamicReplacement(for:). if (constant.isNull()) return; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 3e77b0357db26..aafd1950cd5a5 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -117,6 +117,7 @@ class AttributeChecker : public AttributeVisitor { IGNORED_ATTR(ReferenceOwnership) IGNORED_ATTR(OriginallyDefinedIn) // SWIFT_ENABLE_TENSORFLOW + IGNORED_ATTR(NoDerivative) // TODO(TF-715): Allow @quoted on more decls. IGNORED_ATTR(Quoted) // SWIFT_ENABLE_TENSORFLOW END @@ -260,7 +261,6 @@ class AttributeChecker : public AttributeVisitor { // TODO(TF-999): Remove deprecated `@differentiating` attribute. void visitDifferentiatingAttr(DerivativeAttr *attr); void visitCompilerEvaluableAttr(CompilerEvaluableAttr *attr); - void visitNoDerivativeAttr(NoDerivativeAttr *attr); // SWIFT_ENABLE_TENSORFLOW END }; } // end anonymous namespace @@ -4865,14 +4865,3 @@ void AttributeChecker::visitCompilerEvaluableAttr(CompilerEvaluableAttr *attr) { // checked, and it's not type checked yet, so we check these rules later in // TypeChecker::checkFunctionBodyCompilerEvaluable(). } - -// SWIFT_ENABLE_TENSORFLOW -void AttributeChecker::visitNoDerivativeAttr(NoDerivativeAttr *attr) { - auto &ctx = D->getASTContext(); - // `@noDerivative` implies non-varying semantics for differentiable activity - // analysis. SIL values produced from references to `@noDerivative` - // declarations will not be marked as varying; these values do not need a - // derivative. - D->getAttrs().add( - new (ctx) SemanticsAttr("autodiff.nonvarying", /*implicit*/ true)); -} diff --git a/test/AutoDiff/downstream/Inputs/noderivative_attr_other_file.swift b/test/AutoDiff/downstream/Inputs/noderivative_attr_other_file.swift new file mode 100644 index 0000000000000..b5842532aebf0 --- /dev/null +++ b/test/AutoDiff/downstream/Inputs/noderivative_attr_other_file.swift @@ -0,0 +1,5 @@ +@noDerivative +@_silgen_name("float_to_int_noderivative") +func floatToIntNoDerivative(_ x: Float) -> Int { + Int(x) +} diff --git a/test/AutoDiff/downstream/derived_differentiable.swift b/test/AutoDiff/downstream/derived_differentiable.swift index 8d4f9e52ba218..a76f3d8ffdae1 100644 --- a/test/AutoDiff/downstream/derived_differentiable.swift +++ b/test/AutoDiff/downstream/derived_differentiable.swift @@ -42,7 +42,7 @@ struct TestNoDerivative : EuclideanDifferentiable { // CHECK-AST-LABEL: internal struct TestNoDerivative : EuclideanDifferentiable { // CHECK-AST: var w: Float -// CHECK-AST: @noDerivative @_semantics("autodiff.nonvarying") internal var technicallyDifferentiable: Float +// CHECK-AST: @noDerivative internal var technicallyDifferentiable: Float // CHECK-AST: internal init(w: Float, technicallyDifferentiable: Float) // CHECK-AST: internal struct TangentVector : Differentiable, AdditiveArithmetic, ElementaryFunctions // CHECK-AST: internal typealias TangentVector = TestNoDerivative.TangentVector @@ -55,7 +55,7 @@ struct TestPointwiseMultiplicative : Differentiable { // CHECK-AST-LABEL: internal struct TestPointwiseMultiplicative : Differentiable { // CHECK-AST: var w: PointwiseMultiplicativeDummy -// CHECK-AST: @noDerivative @_semantics("autodiff.nonvarying") internal var technicallyDifferentiable: PointwiseMultiplicativeDummy +// CHECK-AST: @noDerivative internal var technicallyDifferentiable: PointwiseMultiplicativeDummy // CHECK-AST: internal init(w: PointwiseMultiplicativeDummy, technicallyDifferentiable: PointwiseMultiplicativeDummy) // CHECK-AST: internal struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative // CHECK-AST: internal typealias TangentVector = TestPointwiseMultiplicative.TangentVector @@ -68,7 +68,7 @@ struct TestKeyPathIterable : Differentiable, KeyPathIterable { // CHECK-AST-LABEL: internal struct TestKeyPathIterable : Differentiable, KeyPathIterable { // CHECK-AST: var w: Float -// CHECK-AST: @noDerivative @_semantics("autodiff.nonvarying") internal var technicallyDifferentiable: Float +// CHECK-AST: @noDerivative internal var technicallyDifferentiable: Float // CHECK-AST: internal init(w: Float, technicallyDifferentiable: Float) // CHECK-AST: internal struct TangentVector : Differentiable, AdditiveArithmetic, ElementaryFunctions, VectorProtocol, KeyPathIterable // CHECK-AST: internal typealias TangentVector = TestKeyPathIterable.TangentVector diff --git a/test/AutoDiff/downstream/noderivative_attr.swift b/test/AutoDiff/downstream/noderivative_attr.swift index 637dbcc3b38e9..dfc93c7eb5d60 100644 --- a/test/AutoDiff/downstream/noderivative_attr.swift +++ b/test/AutoDiff/downstream/noderivative_attr.swift @@ -28,11 +28,11 @@ struct NotDifferentiable { } // CHECK-LABEL: struct NotDifferentiable { -// CHECK: @noDerivative @_hasStorage @_semantics("autodiff.nonvarying") var stored: Float { get set } -// CHECK: @noDerivative @_semantics("autodiff.nonvarying") var computedProperty: Float { get set _modify } -// CHECK: @noDerivative @_semantics("autodiff.nonvarying") func instanceMethod(_ x: Float) -> Float -// CHECK: @noDerivative @_semantics("autodiff.nonvarying") static func staticMethod(_ x: Float) -> Float -// CHECK: @noDerivative @_semantics("autodiff.nonvarying") subscript(x: Float) -> Float { get set _modify } +// CHECK: @noDerivative @_hasStorage var stored: Float { get set } +// CHECK: @noDerivative var computedProperty: Float { get set _modify } +// CHECK: @noDerivative func instanceMethod(_ x: Float) -> Float +// CHECK: @noDerivative static func staticMethod(_ x: Float) -> Float +// CHECK: @noDerivative subscript(x: Float) -> Float { get set _modify } // CHECK: } // CHECK-LABEL: // NotDifferentiable.computedProperty.getter diff --git a/test/AutoDiff/downstream/noderivative_attr_cross_file.swift b/test/AutoDiff/downstream/noderivative_attr_cross_file.swift new file mode 100644 index 0000000000000..33c34c551a837 --- /dev/null +++ b/test/AutoDiff/downstream/noderivative_attr_cross_file.swift @@ -0,0 +1,8 @@ +// RUN: %target-swift-frontend -emit-sil %S/Inputs/noderivative_attr_other_file.swift %s | %FileCheck %s + +@differentiable +func bar(_ x: Float) -> Float { + return Float(floatToIntNoDerivative(x)) +} + +// CHECK: sil hidden [_semantics "autodiff.nonvarying"] @float_to_int_noderivative : $@convention(thin) (Float) -> Int