I agree with Jerry. On the Arm it is prefetching the pointer before
doing the branch not equal. It has *something* to do with the
casts.
If you take the gcc output and remove all the silly casts and brackets
you get the following:
if (var.gu.type == Lisp_Type_Record &&
((struct lrecord_header*)var.ui)->type == lrecord_type_symbol)
10e4: e2153003 ands r3, r5, #3 ; 0x3
10e8: e1a02003 mov r2, r3
10ec: e5d53000 ldrb r3, [r5] <- bad instruction! bad!
10f0: 1a000441 bne 21fc <signal_1+0x4c4>
Which crashes :-( It loads r5 indirect before the branch.
However, remove the struct cast and replace it with a simple unsigned:
if (var.gu.type == Lisp_Type_Record &&
(*((unsigned*)var.ui) & 0xff) == lrecord_type_symbol)
10e4: e2153003 ands r3, r5, #3 ; 0x3
10e8: e1a02003 mov r2, r3
10ec: 1a000441 bne 21f8 <signal_1+0x4c0>
10f0: e5d53000 ldrb r3, [r5]
And it works :-) Notice that the indirect load is now after the
branch.
Note this also explains why the use_union_type flag is irrelevant
here. It only affects the first part of the if, not the casting part.
I don't know where to go from here. I suppose RECORD_TYPEP could be
modified to do the above cast but I am way out of my depth here.
Cheers,
Sean
P.S. I love the great comment that tells you that 3 decimal is 3 hex.
I learn something new everyday.