Skip to content

LLVM: fix #17920 (register padding)

Sylvain Henry requested to merge hsyl20/ghc:hsyl20/llvm into master

The issue to solve (#17920 (closed)) was that LLVM code generator doesn't support Cmm registers mapped to the same real register and alive at the same time. E.g. F3 and D3. We had this in hand-written Cmm in the RTS because:

  1. of generic SAVE_STGREGS/RESTORE_STGREGS macros that save/restore F1-F6 and D1-D6: fixing this was easy by special casing for x86-64, but it wasn't enough (see 2)
  2. a function using these macros also used jump foo [*] where [*] means that all real registers must be considered alive (cf GHC.Cmm.CallConv.realArgRegsCover). To keep floating-point registers alive, XMM registers (Cmm ones) were used. So even with the patch for 1 we ended up with D1-D6 and XMM1-XMM6 alive at the same time and mapped to XMM registers (real ones).

Commit 1 makes SAVE_REGS/RESTORE_REGS builtin functions that use the same set of registers than jump foo [*] (realArgRegsCover). I had to change the set to use D1-D6 instead of XMM1-XMM6 because the NCG doesn't support load/store of XMM registers (such a shame)...

While working on this stuff, I've had to understand LLVM register padding, so commit 3 adds documentation and refactors a little to give better error message.

Finally I wrote some tests (commit 4). They were failing with CmmToC (unregisterised build) because labels in top-level CmmData automatically led to "extern StgWordArray foo" declarations, leading to type conflicts when we declare something that isn't external nor a word array. This is fixed in commit 3.

With this MR, ./hadrian/build-stack --flavour=quick-llvm -c -j test passes for me on x86-64/linux

Edited by Sylvain Henry

Merge request reports