-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[sil-optimizer] Add FP comparison support in constant folder #69828
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
Conversation
@BradLarson could you please trigger swift-ci? |
@eeckstein could you please take a look at the PR? |
bool result; | ||
bool isOrdered = !lhs.isNaN() && !rhs.isNaN(); | ||
|
||
switch (ID) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please ensure your coding style is same as in the file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually git-clang-format
. But I can bypass that step to keep the style same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well... git-clang-format
is dumb and overall the style guide is not simply clang-format everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not simply clang-format everything.
Shouldn't it be? What is the benefit of using a formatter then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can handle maybe 80% of cases. However, the remaining 20% of cases are about things like readability, etc.
However, in your particular case it's not configured properly. The repo's style config is explicitly saying based on LLVM
. And LLVM defaults to 2 spaces indent. So, something is not correct here and this is why one need to examine the output of formatter not merely commit it as-is.
@@ -40,7 +40,12 @@ func caller_of_simple_vjp() -> Float { | |||
@_silgen_name("pb_with_control_flow") | |||
func pb_with_control_flow(_ x: Float) -> Float { | |||
if (x > 0) { | |||
return sin(x) * cos(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just ensure you won't have x
constant folded here. For example, you could have an argument of caller_of_pb_with_control_flow
that you will use to evaluate gradient at.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah nice catch. Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Do you mind adding a swift (not sil) test file which compares constant folded results with not-constant folded floating point operations? This would not only test the implementation but also the assumptions about the floating point behavior (like "Ordered comparisons with NaN always return false", etc).
You can do that for example by generating the test file, like e.g. done here: https://github.com/apple/swift/blob/main/validation-test/SILOptimizer/static_enums_fuzzing.swift.
Then it's easy to test all combinations of fp-types * operations * relevant-operand-values
@eeckstein Added the validation tests as you suggested. They helped catch quite a lot of edge cases so thanks for pointing it out here! Can you please take a look at the revision when you get time? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! Thanks!
LGTM
} | ||
} | ||
|
||
func generateComparisonFuncDecls() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong indentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@inline(never) @_silgen_name("\(comparisonFuncName)") @_optimize(none) | ||
func \(comparisonFuncName)() { | ||
let \(resultVarName) = \(optFuncName)() == \(unoptFuncName)() | ||
print("[\(resultVarName)] result equal? \\(\(resultVarName))") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could just emit a precondition(result, "message")
instead of FileChecking the output. But checking the output is also fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Changed.
@eeckstein we may need to restart swift-ci. |
@swift-ci please test |
Looks like a validation test failed. I'm taking a look. |
Fixed the failing validation test.
|
@swift-ci Please test |
@eeckstein I believe this can be merged? |
Basically yes. |
This commit modifes the constant folder to not handle equality comparisons b/w infinity and non-infinity operands. In such comparisons, special floating point types - Float80 and Float16, may come into play and pattern matching againt them complicates the constant folding logic more than we'd like.
@eeckstein Here's my changes rebased on top of trunk. Can you please kick off swift-ci? |
@swift-ci test |
Windows build seems to have timed out. |
@swift-ci please test windows |
CC: @stephentyrone |
@jkshtj -- Do the LLVM optimizations not handle these cases? Generally, LLVM is pretty good at this sort of thing. |
@tbkka we were motivated to perform FP constant-folding at the SIL level because it vastly simplified the generated derivative code. Below is a minimal example of the optimizations we wanted the FP constant-folding to enable. @differentiable(reverse)
func f(_ x: Float) -> Float {
if (x > 0) {
return sin(x) * cos(x)
} else {
return sin(x) + cos(x)
}
}
// With FP constant-folding the control-flow in VJP of `f`
// is removed after it's inlined into `foo`, which eventually
// enables further inlining of all VJPs and pullbacks involved.
//
// Inlining of VJPs and pullbacks lets us get rid of closure context
// allocations, which form the most latent chunk of AD code.
@inline(never)
func foo() -> Float {
gradient(at: Float(4), of: f(x) )
} |
This pull request adds support for handling floating point comparisons to the constant folder.
Partially fixes #68901