Skip to content

[DynamicCast] Rely on runtime when casts can't be optimized #33761

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 2 commits into from
Oct 28, 2020

Conversation

tbkka
Copy link
Contributor

@tbkka tbkka commented Sep 2, 2020

The Swift compiler renders as? operations in Swift into variations of the checked_cast_br instructions in SIL. Subsequent optimization passes may alter or eliminate these instructions. Any remaining cast instructions after optimization are translated by IRGen into runtime calls.

At least, that's the theory. Unfortunately, the current IRGen logic does not recognize all of the casting instruction variants and translates one particular unrecognized variant into a simple nil load. This effectively converts an as? operation into one that will always fail. Specifically, this occurs for optimized casts of metatypes to AnyObject:

  let a = Int.self
  let b = a as? AnyObject
  // b should not be nil here

(Ironically, in this particular case, the frontend issues a diagnostic warning that the cast will always succeed.)

This PR changes this case in IRGen to instead generate a call to swift_dynamicCast, deferring this case to the runtime. (Yes, this particular example should get optimized into a simple store, but that's a future project.)

Test suite changes:

  • With this change, the "BoxingCasts" test suite (which exercises a variety of boxing and unboxing casts) now passes in both optimized and non-optimized builds, so I've enabled those versions.
  • There was a SIL test previously that constructed a checked_cast_br instruction with a thin metatype. The IRGen pass should never see instructions of this form, so I've changed that particular test to exercise a thick metatype instead.

@tbkka
Copy link
Contributor Author

tbkka commented Sep 2, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Sep 2, 2020

Build failed
Swift Test Linux Platform
Git Sha - 1e203eb3b79eefe3ca93b592f9e6e3a57138f6dd

@swift-ci
Copy link
Contributor

swift-ci commented Sep 2, 2020

Build failed
Swift Test OS X Platform
Git Sha - 1e203eb3b79eefe3ca93b592f9e6e3a57138f6dd

Copy link
Contributor

@jckarter jckarter left a comment

Choose a reason for hiding this comment

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

Makes sense. We shouldn't try to peephole these in IRGen; we should let the cast optimizer do that if possible.

@tbkka
Copy link
Contributor Author

tbkka commented Sep 8, 2020

@swift-ci Please test macOS

@swift-ci
Copy link
Contributor

swift-ci commented Sep 8, 2020

Build failed
Swift Test OS X Platform
Git Sha - 1e203eb3b79eefe3ca93b592f9e6e3a57138f6dd

@tbkka
Copy link
Contributor Author

tbkka commented Sep 10, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 1e203eb3b79eefe3ca93b592f9e6e3a57138f6dd

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 1e203eb3b79eefe3ca93b592f9e6e3a57138f6dd

@shahmishal
Copy link
Member

Please update the base branch to main by Oct 5th otherwise the pull request will be closed automatically.

  • How to change the base branch: (Link)
  • More detail about the branch update: (Link)

@tbkka tbkka changed the base branch from master to main October 1, 2020 22:12
@tbkka
Copy link
Contributor Author

tbkka commented Oct 5, 2020

Looks like the Linux test is failing in optimized builds due to some issue with ARC. I'm trying to isolate whether it's an issue with my change or is an existing bug in the compiler ARC optimizations.

@tbkka
Copy link
Contributor Author

tbkka commented Oct 7, 2020

Thanks to @eeckstein for fixing the ARC bug I was tripping over. Now let's try those tests again!

@tbkka
Copy link
Contributor Author

tbkka commented Oct 7, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Oct 7, 2020

Build failed
Swift Test Linux Platform
Git Sha - 88fc76f450360365aec5b692376482e3bfd370c6

@tbkka
Copy link
Contributor Author

tbkka commented Oct 8, 2020

Linux is crashing on the optimized form of this test:

[ RUN      ] BoxingCasts.test184(): Casting SwiftValueBox(AnyHashable(ClassInt)) to ClassInt
stderr>>> CRASHED: SIGSEGV
the test crashed unexpectedly
[     FAIL ] BoxingCasts.test184(): Casting SwiftValueBox(AnyHashable(ClassInt)) to ClassInt

@tbkka
Copy link
Contributor Author

tbkka commented Oct 13, 2020

@swift-ci Please test Linux

@tbkka
Copy link
Contributor Author

tbkka commented Oct 13, 2020

Re-ran the full Linux test locally and it's passing for me. Hmmm.... I'll try the CI bot again and see if that still fails before I spend time digging further.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 88fc76f450360365aec5b692376482e3bfd370c6

@tbkka
Copy link
Contributor Author

tbkka commented Oct 15, 2020

Re-ran the Linux test locally on Ubuntu 16.04 (required upgrading clang-3.8 to clang-12), and it all passes just fine. I guess I'll try again with the CI preset and see??

@tbkka
Copy link
Contributor Author

tbkka commented Oct 16, 2020

Still having trouble reproducing this locally. I'll try again with the exact build options used on the CI bot.

@tbkka tbkka force-pushed the tbkka/dynamicCastRework-IRGen-GenCast branch 2 times, most recently from 1f2335d to e5381bd Compare October 17, 2020 01:14
@tbkka
Copy link
Contributor Author

tbkka commented Oct 17, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - e5381bddc6ba8a6c3584734390fd14e51ac0a99d

@tbkka tbkka force-pushed the tbkka/dynamicCastRework-IRGen-GenCast branch from e5381bd to 318935e Compare October 17, 2020 01:38
@tbkka
Copy link
Contributor Author

tbkka commented Oct 17, 2020

@swift-ci Please test

@tbkka
Copy link
Contributor Author

tbkka commented Oct 17, 2020

Let's see if the test that's been failing on Linux also fails on macOS when you enable it properly.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 4c3818b895f866fc73259742b62134be91999ffe

@tbkka
Copy link
Contributor Author

tbkka commented Oct 19, 2020

Same cast was in a disabled test in Casts.swift, so I also enabled that unconditionally.

With that, I can now consistently reproduce it on Linux. The root cause seems to be another variation of the ARC issue that @eeckstein fixed for me earlier. As before, it fails on Linux because it triggers __SwiftValue boxing which behaves slightly differently on Linux than on macOS.

@tbkka tbkka force-pushed the tbkka/dynamicCastRework-IRGen-GenCast branch from 4c3818b to 543d4fc Compare October 21, 2020 20:33
@tbkka
Copy link
Contributor Author

tbkka commented Oct 22, 2020

I believe #34383 will resolve the last test failure here.

@tbkka
Copy link
Contributor Author

tbkka commented Oct 22, 2020

#34383
@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 543d4fcb38e38ddf1109e983c9ed6f3da942d5a7

tbkka added 2 commits October 28, 2020 10:57
The Swift compiler renders `as?` operations in Swift into variations of the
`checked_cast_br` instructions in SIL.  Subsequent optimization passes may alter
or eliminate these instructions.  Any remaining instructions after optimization
are translated by IRGen into runtime calls.

At least, that's the theory.  Unfortunately, the current IRGen logic does not
recognize all of the casting instruction variants and renders one particular
unrecognized variant as a simple nil load.  Specifically, this occurs for
optimized casts of metatypes to AnyObject:
```
  let a = Int.self
  let b = a as? AnyObject
  // b should not be nil here
```

This PR changes this case in IRGen to instead generate a call to
`swift_dynamicCast`, deferring this case to the runtime.

Future:  Someday, the compiler should be taught to correctly optimize
this cast away.
I think this exercises the same optimizer path that's breaking
another test I've been staring at.
@tbkka tbkka force-pushed the tbkka/dynamicCastRework-IRGen-GenCast branch from 543d4fc to 35aa75a Compare October 28, 2020 18:02
@tbkka
Copy link
Contributor Author

tbkka commented Oct 28, 2020

Now that #34383 has landed, let's try this again.

@tbkka
Copy link
Contributor Author

tbkka commented Oct 28, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 35aa75a

@tbkka
Copy link
Contributor Author

tbkka commented Oct 28, 2020

@swift-ci Please clean test Linux

@tbkka tbkka merged commit b0675c0 into swiftlang:main Oct 28, 2020
ainu-bot added a commit to google/swift that referenced this pull request Oct 29, 2020
* 'main' of github.com:apple/swift:
  [DynamicCast] Rely on runtime when casts can't be optimized (swiftlang#33761)
@tbkka tbkka deleted the tbkka/dynamicCastRework-IRGen-GenCast branch August 1, 2024 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants