My team has run into an interesting problem when attempting to compile ModuleScripts with NCG enabled.
On x86-64 devices, NCG compiles completely fine. Compilation runs as usual, and the game join process is smooth.
On ARM64 devices, the IR phase of NCG fails for our Crypto ModuleScripts, and we get lowering errors printed in the Console. (Note: this has only been tested on Mac M1)
On Snapdragon processors, the machine code makes it to execution, causing a hard crash of not only the Roblox App, but a soft reboot of the phone (probably because bad ARM64 machine code was piped to the CPU, raising an Undefined Instruction Exception)
There are code complexity limits that can be reached in certain functions, so some failures are expected.
This failures are not preventing code execution in the VM, so it is not blocking you from releasing your experience.
Of course we aim to never have those failures, so we have work planned to improve ARM64 lowering and avoid the limit in these hashing functions.
As for the crash, we could not confirm that it is related to NCG so it is more likely to be some different issue (the log you provided has more errors about Vulkan rendering).
You should open a separate bug report for that crash and provide us with a way to reproduce it.
Was this caused because ARM64 has fewer registers compared to others or something? Leading to register spilling issues in ncg for functions with many live values?
ARM64 actually had more registers than x64 and while it does support spilling, it did not trigger it in a few key locations leading to this failure.
x64 would actually begin spilling earlier and that allowed it to support more live values than arm64 without required spills.
Having a quick look at the register allocation setup, I see ARM64 is only using 18 of its 31 general purpose registers (avoiding x19 x28 callee saved registers and X0-X13, but I think thats from SME) and 24 of 32 SIMD registers. So while ARM64 theoretically has more registers than x64, was the actual usable register count limited to be similar to or even lower than x64 because codegen might not be using that much in context? Or maybe saving overhead, not sure just had a quick look.
Available upper registers are non-volatile and require preservation, which in turn uses extra stack size reducing the general-purpose spill area size.
We might still rebalance to use a few more of ‘x’ registers, but previously we saw more pressure on ‘q’ registers so we allocated accordingly.
May you explain why spilling was not being triggered in some places (From what I know as of now, spilling will trigger when the allocator runs out of the explicitly allowed register sets passed in IrLoweringA64 :