On 23/03/2012 00:59, Logan Bell wrote:
Nick,
I went ahead and created a JIRA story with the original e-mail of this
thread:
https://issues.apache.org/jira/browse/LUCY-216
On this ticket you should see 4 attachments:
Inversion.sO0 19kb (Without optimization)
Inversion.sO0 4kb (Ignore, this was a mistake unable to figure out how to
delete from Jira)
Inversion.sO1 16kb (With optimization)
Thanks, Logan. This is definitely a compiler bug. Here's the relevant
part of the assembler output for the inner loop of Inversion_invert
(comments are mine):
LBB12_4:
movq (%rbx), %rax # cur_token = *tokens;
movl %r9d, 48(%rax) # cur_token->pos = token_pos;
movl 44(%rax), %eax # %eax = cur_token->pos_inc
testl %eax, %eax
leal (%rax,%r9), %r15d # %r15d = %eax + token_pos
jns LBB12_6
[ code for THROW(...) ]
LBB12_6:
addq $8, %rbx
cmpq %r14, %rbx
movl %r15d, %r9d
jb LBB12_4
The "if" statement in the loop is compiled to the following instructions:
testl %eax, %eax
jns LBB12_6
Where %eax contains cur_token->pos_inc. So the "if" statement basically
becomes:
if (cur_token->pos_inc < 0)
Which is of course bogus. It really makes me wonder why the compiler
gets this very simple loop wrong. My best guess is that clang tries to
optimize the standard way to test for integer overflow in C and somehow
gets it wrong. Since overflows rarely happen, this could explain why
this bug wasn't noticed early on.
Nick