mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add a new mandatory BooleanLiteralFolding pass which constant folds conditional branches with boolean literals as operands.
```
%1 = integer_literal -1
%2 = apply %bool_init(%1) // Bool.init(_builtinBooleanLiteral:)
%3 = struct_extract %2, #Bool._value
cond_br %3, bb1, bb2
```
->
```
...
br bb1
```
This pass is intended to run before DefiniteInitialization, where mandatory inlining and constant folding didn't run, yet (which would perform this kind of optimization).
This optimization is required to let DefiniteInitialization handle boolean literals correctly.
For example in infinite loops:
```
init() {
while true { // DI need to know that there is no loop exit from this while-statement
if some_condition {
member_field = init_value
break
}
}
}
```
71 lines
2.1 KiB
Swift
71 lines
2.1 KiB
Swift
// RUN: %target-run-simple-swift
|
|
// REQUIRES: executable_test
|
|
|
|
// Would fail due to unavailability of swift_autoDiffCreateLinearMapContext.
|
|
|
|
import StdlibUnittest
|
|
import DifferentiationUnittest
|
|
|
|
var AddressOnlyTangentVectorTests = TestSuite("AddressOnlyTangentVector")
|
|
|
|
// TF-1149: Test loadable class type with an address-only `TangentVector` type.
|
|
|
|
AddressOnlyTangentVectorTests.test("LoadableClassAddressOnlyTangentVector") {
|
|
final class LoadableClass<T: Differentiable>: Differentiable {
|
|
@differentiable(reverse)
|
|
var stored: T
|
|
|
|
@differentiable(reverse)
|
|
init(_ stored: T) {
|
|
self.stored = stored
|
|
}
|
|
|
|
@differentiable(reverse)
|
|
func method(_ x: T) -> T {
|
|
stored
|
|
}
|
|
}
|
|
|
|
@differentiable(reverse)
|
|
func projection<T: Differentiable>(_ s: LoadableClass<T>) -> T {
|
|
var x = s.stored
|
|
return x
|
|
}
|
|
expectEqual(.init(stored: 1), gradient(at: LoadableClass<Float>(10), of: projection))
|
|
|
|
@differentiable(reverse)
|
|
func tuple<T: Differentiable>(_ s: LoadableClass<T>) -> T {
|
|
var tuple = (s, (s, s))
|
|
return tuple.1.0.stored
|
|
}
|
|
expectEqual(.init(stored: 1), gradient(at: LoadableClass<Float>(10), of: tuple))
|
|
|
|
@differentiable(reverse)
|
|
func conditional<T: Differentiable>(_ s: LoadableClass<T>) -> T {
|
|
var tuple = (s, (s, s))
|
|
// TODO: cannot use literal `false` because it crashes
|
|
if 1 == 0 {}
|
|
return tuple.1.0.stored
|
|
}
|
|
expectEqual(.init(stored: 1), gradient(at: LoadableClass<Float>(10), of: conditional))
|
|
|
|
@differentiable(reverse)
|
|
func loop<T: Differentiable>(_ array: [LoadableClass<T>]) -> T {
|
|
var result: [LoadableClass<T>] = []
|
|
for i in withoutDerivative(at: array.indices) {
|
|
result.append(array[i])
|
|
}
|
|
return result[0].stored
|
|
}
|
|
expectEqual([.init(stored: 1)], gradient(at: [LoadableClass<Float>(10)], of: loop))
|
|
|
|
@differentiable(reverse)
|
|
func arrayLiteral<T: Differentiable>(_ s: LoadableClass<T>) -> T {
|
|
var result: [[LoadableClass<T>]] = [[s, s]]
|
|
return result[0][1].stored
|
|
}
|
|
expectEqual(.init(stored: 1), gradient(at: LoadableClass<Float>(10), of: arrayLiteral))
|
|
}
|
|
|
|
runAllTests()
|