[GHC] #9391: LLVM 3.2 crash (AVX messes up GHC calling convention)
GHC
ghc-devs at haskell.org
Fri Aug 1 12:23:34 UTC 2014
#9391: LLVM 3.2 crash (AVX messes up GHC calling convention)
-------------------------------------+-------------------------------------
Reporter: scpmw | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (LLVM) | Version: 7.8.2
Keywords: | Operating System: MacOS X
Architecture: Unknown/Multiple | Type of failure: Runtime
Difficulty: Easy (less than 1 | crash
hour) | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Revisions:
-------------------------------------+-------------------------------------
I stumbled across the problem of LLVM 3.2 builds seemingly randomly
crashing on my Mac. After quite a bit of investigation I found that the
source of the problem was somewhere in the `base` library (`span` to be
precise), where it encountered Cmm like follows:
{{{
cp7n:
if ((Sp + -56) < SpLim) goto cp8c; else goto cp8d;
...
cp8d:
I64[Sp - 40] = block_cp7g_info;
_smKL::P64 = P64[R1 + 7];
_smKO::P64 = P64[R1 + 15];
_smKP::P64 = P64[R1 + 23];
_smL0::P64 = P64[R1 + 31];
R1 = R2;
P64[Sp - 32] = _smKL::P64;
P64[Sp - 24] = _smKO::P64;
P64[Sp - 16] = _smKP::P64;
P64[Sp - 8] = _smL0::P64;
Sp = Sp - 40;
if (R1 & 7 != 0) goto up8R; else goto cp7h;
up8R:
call block_cp7g_info(R1) args: 0, res: 0, upd: 0;
...
}}}
which leads LLVM 3.2 to produce the following assembly:
{{{
_smL1_info: ## @smL1_info
## BB#0: ## %cp7n
pushq %rbp
movq %rsp, %rbp
movq %r14, %rax
movq %rbp, %rcx
leaq -56(%rcx), %rdx
cmpq %r15, %rdx
jae LBB160_1
...
LBB160_1: ## %cp8d
leaq _cp7g_info(%rip), %rdx
movq %rdx, -40(%rcx)
vmovups 7(%rbx), %ymm0
vmovups %ymm0, -32(%rcx)
addq $-40, %rcx
testb $7, %al
je LBB160_4
## BB#2: ## %up8R
movq %rcx, %rbp
movq %rax, %rbx
popq %rbp
vzeroupper
jmp _cp7g_info ## TAILCALL
}}}
So here LLVM has figured out that it can use `vmovups` in order to move 4
words at the same time. However, there is a puzzling side effect: All of
sudden we have a `pushq %rbp` at the start of the function with a matching
`popq %rbp` at the very end. This overwrites the stack pointer update
(`movq %rcx, %rbp`) and - unsurprisingly - causes the program to crash
rather quickly.
My interpretation is that LLVM 3.2 erroneously thinks that AVX
instructions are incompatible with frame pointer elimination. The
reasoning is that this is exactly the kind of code LLVM generates if we
disable this "optimisation" (`--disable-fp-elim`). Furthermore, disabling
AVX instructions (`-mattr=-avx`) fixes the problem - LLVM falls back to
the less efficient `movups`, with `pushq $rbp` vanishing as well. Finally,
this bug seems to happen exactly with LLVM 3.2, with 3.3 upwards
generating correct code.
My proposed fix would be to add `-mattr=-avx` to the `llc` command line by
default for LLVM 3.2. This issue might be related to #7694.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9391>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list