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
Add sextOrBitCast to conversions of Builtin.Word #19600
Conversation
FYI, I'm still doing a couple last checks on this change. It should be fine, but I re-enabled the zext conversions after my last build. It also lacks a discrete test. But I'd be happy to take pointers on what sort of test this should have. |
A test may have to be written in SIL for the iPhone simulator, if that's the only place this change is visible on Darwin. @eeckstein who can advise? |
An error was hit when attempting to build Swift on a 32-bit Linux host. It was asserting when attempting to run ‘RedunantLoadElim” during the optimizer. The reason why is a bit messy. First, Builtin.Word is always considered to be 64-bit when it is a SILType. This means the optimizer, when working with a Builtin.Word, will create 64-bit APInts when converting from other types. Second, the SIL being output for a particular literal looked like this: Int2048 (integer_literal) : Int32 (Signed Truncation) : Word (zextOrBitCast) The constant fold behavior would convert this into an integer_literal of the Builtin.Word type. But because of the zext cast, if the original literal was -1, it would become +4 billion during folding. This normally isn’t a problem **except** when SIL is still attempting to optimize. (See First) Third, The Redundant Load Elimination pass was attempting to make sense of an index_addr instruction which was indexing at -1. This happens when you perform “-= 1” on an UnsafePointer. Because SIL was interpreting Word’s size incorrectly, it caused the RLE pass to ask “what is the ProjectionKind at ptr[4billion]?” Since there’s no feasible answer for such a question, the answer was “nothing” when the Projection’s kind() was checked, which tripped the assert. This fix uses sign extension when converting “upward” and the Integer type is signed, otherwise it will still use zero extension.
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.
LGTM
I've updated with the feedback from @xwu and my last set of checks with that version are good. @milseman Regarding the test, I'm not 100% sure that writing it in SIL really helps? The change only affects the SIL generated from the Int32/UInt32 (and Int64/UInt64) types, and so any test in SIL is really testing the "Builtin.Word is always 64-bit during Optimization" behavior during constant folding. Although maybe @eeckstein has a better idea how to write a test to prevent regressions here. EDIT: Alternatively, since this bug causes a build break and you cannot build the stdlib if the Optimizer is throwing a fit, perhaps that is a sufficient test for now? But if that's true, it does stress the need for a reliable CI node on a 32-bit Linux host. x86 Linux would be ideal for this, IMO, but the ELF32 dynamic linker issues with LLVM would need to be fixed before that can be reality. |
I feel like a source-level test would be the most robust thing. Execution-testing some Swift code that exercises one of the formerly problematic situations should be more robust and ensure that any refactorings we do in the future here don't break things even if all the implementation details completely change. |
So effectively a snippet where if it compiles, the test passes, and if it doesn't compile, the test fails? Something like the following maybe?
|
This fix is in the stdlib. Regarding tests: I agree with @jckarter that the best test for the stdlib fix would be an execution test. |
Which is fair, although the fix for SIL Optimizer is a bit more complicated (the thread is gnarly with details). I kinda hope the plan there wouldn't be to just abort the optimization if given a nonsense location to check for loading? The real fix should be to actually fix it so that Builtin.Word is the correct size for the target so constant folding doesn't produce the nonsense, but seeing as that's been marked with FIXMEs already, I suspect someone's already looked at the amount of work that is and decided against it at that time. My thoughts here are that the RLE piece is behaving as expected by asserting that ptr[4294967295] is nonsensical when creating the swift::Projection. What do you think the fix is here? |
Turns out there’s already a test for RLE which catches this issue, it’s just a bit hard to run when stdlib is failing to build. So the SIL test for this does exist, and does fail, even with the stdlib fix. So, I’ll eat my hat a bit, since I guess it’s also established in the code history that this optimization shouldn’t be failing like this. |
@swift-ci Please test |
Build failed |
Build failed |
Ugh, it looks like the CI doesn't like that I did an amend commit here. Lesson Learned. |
No problem, it restarts automatically. |
Yeah, just weird that it was trying to sync a commit that no longer exists. |
Yeah, that's unfortunately a bug in the Jenkins git plugin we've had to live with for a while. |
An error was hit when attempting to build Swift on a 32-bit Linux host. It was asserting when attempting to run ‘RedunantLoadElim” during the optimizer. The reason why is a bit messy.
First, Builtin.Word is always considered to be 64-bit when it is a SILType. This means the optimizer, when working with a Builtin.Word, will create 64-bit APInts when converting from other types.
Second, the SIL being output for a particular literal looked like this:
Int2048 (integer_literal) : Int32 (Signed Truncation) : Word (zextOrBitCast)
The constant fold behavior would convert this into an integer_literal of the Builtin.Word type. But because of the zext cast, if the original literal was -1, it would become +4 billion during folding.
This normally isn’t a problem except when SIL is still attempting to optimize. (See First)
Third, The Redundant Load Elimination pass was attempting to make sense of an index_addr instruction which was indexing at -1. This happens when you perform “-= 1” on an UnsafePointer. Because SIL was interpreting Word’s size incorrectly, it caused the RLE pass to ask “what is at ptr[4billion]?” Since there’s no feasible answer for such a question, the answer was “nothing”, which tripped the assert.
This fix uses sign extension when converting “upward” and the Integer type is signed, otherwise it will still use zero extension.
Resolves SR-8870.