http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54089
--- Comment #18 from Oleg Endo <olegendo at gcc dot gnu.org> 2012-09-17 23:29:52 UTC --- Created attachment 28207 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=28207 Arithmetic right shift rework I have tried to apply the same strategies to the arithmetic right shift patterns as for logical right/left shift patterns. What happens then is that combine will see arithmetic right shift patterns (for shift amounts > 1) and will fail to convert arithmetic right shifts to logical right shifts where it would actually be possible. This results in bigger code since arithmetic shifts on SH are more expensive than logical shifts. Unfortunately, combine will only do the shift type conversion if it can combine the logical shift with some other insn -- which is not very likely on SH. Thus, the logical shift is discarded. If however, no arithmetic shift pattern is there that matches the shift amount (which is currently the case), combine will split out the logical shift. Not having arithmetic right shift patterns makes it difficult to write combine patterns for things like ... char test (int x) { return x >> 24; } which ends up as: -m4: mov #-24,r1 shad r1,r4 rts exts.b r4,r0 -m2: mov.l .L3,r1 sts.l pr,@-r15 jsr @r1 nop mov lds.l @r15+,pr rts nop .L4: .align 2 .L3: .long ___ashiftrt_r4_24 On the other hand, the following is handled almost as expected: unsigned char test (int a) { return a >> 24; } -m4: mov r4,r0 shlr16 r0 rts shlr8 r0 -m2: mov.l .L3,r1 sts.l pr,@-r15 jsr @r1 nop extu.b r4,r0 lds.l @r15+,p rts nop .L4: .align 2 .L3: .long ___ashiftrt_r4_24 According to my understanding, to fix those issues something like the attached patch would be required. However, it would also require a separate arithmetic right shift to logical right shift conversion pass.