https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63411
--- Comment #2 from bin.cheng <amker.cheng at gmail dot com> ---
(In reply to Oleg Endo from comment #0)
> Compiling the following as C or C++:
>
> typedef struct
> {
> unsigned char sprindex;
> unsigned char y;
> unsigned char index;
> unsigned char attr;
> unsigned char x;
> unsigned short pattern;
> } oam;
>
> extern oam OAM3[8];
>
> int test2 (unsigned c, int r)
> {
> for (unsigned i = 0; i < c; ++i)
> {
> oam* s = &(OAM3[i]);
> if (s->attr & 0x40)
> r += s->pattern;
> }
> return r;
> }
>
> on SH (big or little endian, any CPU type) with -O2 results in the following
> wrong code:
>
> _test2:
> tst r4,r4
> bt .L12
> mov.l .L14,r1
> .align 2
> .L4:
> mov.b @r1,r0
> tst #64,r0
> bt/s .L3
> mov r1,r2
> add #3,r2 <<< wrong struct offset '3'
But r2 is initialized with [.L14] which is _OAM3+3, so the offset actually is 6
here, No?
> mov.w @r2,r2 <<< should be '3*2', i.e. '6'.
> extu.w r2,r2
> add r2,r5
> .L3:
> dt r4
> bf/s .L4
> add #8,r1
> .L12:
> rts
> mov r5,r0
> .L15:
> .align 2
> .L14:
> .long _OAM3+3
> .size _test2, .-_test2
> .ident "GCC: (GNU) 4.9.2 20140929 (prerelease)"
>
>
> Disabling ivopt with '-fno-ivopts' produces correct code:
>
> _test2:
> tst r4,r4
> bt .L12
> mov #0,r2
> mov.l .L14,r3
> .align 2
> .L4:
> mov r2,r1
> shll2 r1
> add r1,r1
> add r3,r1
> mov.b @(3,r1),r0
> tst #64,r0
> bt .L3
> mov.w @(6,r1),r0 <<< correct struct offset '6'
> extu.w r0,r1
> add r1,r5
> .L3:
> dt r4
> bf/s .L4
> add #1,r2
> .L12:
> rts
> mov r5,r0
> .L15:
> .align 2
> .L14:
> .long _OAM3
> .size _test2, .-_test2
> .ident "GCC: (GNU) 4.9.2 20140929 (prerelease)"
>
>
> I haven't checked whether this happens on other targets, but I guess this is
> not SH specific.
>
> This happens on the current 4.9 branch and trunk. 4.8 branch is not
> affected.