https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49263
--- Comment #35 from Alexander Klepikov <klepikov.alex+bugs at gmail dot com> --- (In reply to Oleg Endo from comment #34) > Bit-tests of char and unsigned char should be covered by the test-suite and > should work -- at least originally. However, what might be triggering this > problem is the '== FLAG' comparison. When I was working on this issue I > only used '== 0' or '!= 0' comparison. I can imagine that your test code > triggers some other middle end optimizations and hence we get this. Yes, I am sure that the problem is the '== FLAG' comparison. Before I reported that bug, I tried to bypass it and this macro does not produce shift instructions even on GCC 4.7: #define BIT_MASK_IS_SET_(VALUE, BITMASK)\ ({int _value = VALUE & BITMASK,\ _result;\ if (_value == BITMASK){\ _result = 1;\ }\ else {\ _result = 0;\ }\ _result;}) So this is definitely the comparison. > > Can you try to rewrite your test code to something like this? > > unsigned int f(char v){ > return (v & FLAG) != 0; > } > > ... and see if it generates the tst instruction as expected? > As I understand, you meant the following (I added new functions at the end of file): $ cat f.c #define ADDR 0xFFFF0000 #define P ((unsigned char *)ADDR) #define FLAG 0x40 #define S 7 unsigned char f_char_var(char v){ return (v & FLAG) == FLAG; } unsigned char f_unsigned_char_var(unsigned char v){ return (v & FLAG) == FLAG; } unsigned char f_symbol(void){ return (*P & FLAG) == FLAG; } unsigned char f_symbol_zero(void){ return (*P & FLAG) == 0; } unsigned char f_symbol_non_zero(void){ return (*P & FLAG) != 0; } Compiler flags: -c -mrenesas -m2e -mb -O -fno-toplevel-reorder With patch disabled: $ cat f_clean.s .file "f.c" .text .text .align 1 .global _f_char_var .type _f_char_var, @function _f_char_var: sts.l pr,@-r15 mov.l .L3,r1 jsr @r1 exts.b r4,r4 mov r4,r0 and #1,r0 lds.l @r15+,pr rts nop .L4: .align 2 .L3: .long ___ashiftrt_r4_6 .size _f_char_var, .-_f_char_var .align 1 .global _f_unsigned_char_var .type _f_unsigned_char_var, @function _f_unsigned_char_var: sts.l pr,@-r15 mov.l .L7,r1 jsr @r1 exts.b r4,r4 mov r4,r0 and #1,r0 lds.l @r15+,pr rts nop .L8: .align 2 .L7: .long ___ashiftrt_r4_6 .size _f_unsigned_char_var, .-_f_unsigned_char_var .align 1 .global _f_symbol .type _f_symbol, @function _f_symbol: sts.l pr,@-r15 mov.l .L11,r1 mov.b @r1,r4 mov.l .L12,r1 jsr @r1 nop mov r4,r0 and #1,r0 lds.l @r15+,pr rts nop .L13: .align 2 .L11: .long -65536 .L12: .long ___ashiftrt_r4_6 .size _f_symbol, .-_f_symbol .align 1 .global _f_symbol_zero .type _f_symbol_zero, @function _f_symbol_zero: mov.l .L15,r1 mov.b @r1,r0 tst #64,r0 rts movt r0 .L16: .align 2 .L15: .long -65536 .size _f_symbol_zero, .-_f_symbol_zero .align 1 .global _f_symbol_non_zero .type _f_symbol_non_zero, @function _f_symbol_non_zero: sts.l pr,@-r15 mov.l .L19,r1 mov.b @r1,r4 mov.l .L20,r1 jsr @r1 nop mov r4,r0 and #1,r0 lds.l @r15+,pr rts nop .L21: .align 2 .L19: .long -65536 .L20: .long ___ashiftrt_r4_6 .size _f_symbol_non_zero, .-_f_symbol_non_zero .ident "GCC: (GNU) 12.3.0" With patch enabled: $ cat f.s .file "f.c" .text .text .align 1 .global _f_char_var .type _f_char_var, @function _f_char_var: mov r4,r0 tst #64,r0 mov #-1,r0 rts negc r0,r0 .size _f_char_var, .-_f_char_var .align 1 .global _f_unsigned_char_var .type _f_unsigned_char_var, @function _f_unsigned_char_var: mov r4,r0 tst #64,r0 mov #-1,r0 rts negc r0,r0 .size _f_unsigned_char_var, .-_f_unsigned_char_var .align 1 .global _f_symbol .type _f_symbol, @function _f_symbol: mov.l .L4,r1 mov.b @r1,r0 tst #64,r0 mov #-1,r0 rts negc r0,r0 .L5: .align 2 .L4: .long -65536 .size _f_symbol, .-_f_symbol .align 1 .global _f_symbol_zero .type _f_symbol_zero, @function _f_symbol_zero: mov.l .L7,r1 mov.b @r1,r0 tst #64,r0 rts movt r0 .L8: .align 2 .L7: .long -65536 .size _f_symbol_zero, .-_f_symbol_zero .align 1 .global _f_symbol_non_zero .type _f_symbol_non_zero, @function _f_symbol_non_zero: mov.l .L10,r1 mov.b @r1,r0 tst #64,r0 mov #-1,r0 rts negc r0,r0 .L11: .align 2 .L10: .long -65536 .size _f_symbol_non_zero, .-_f_symbol_non_zero .ident "GCC: (GNU) 12.3.0" > I'm not sure what the purpose of the '-mdisable-dynshift' option would be > here though. For '-m2e' TARGET_DYNSHIFT is already 'false'. So the option > seems misnamed. I choose that name because I wanted to disable dynamic shift instructions for all CPUs. I did not hope that it will affect SH-2E code in such way. I can rewrite the patch so that it only affects CPUs that do not support dynamic shifts and disables library call for dynamic shifts. I'll do it anyway because I need it badly. How do you think, what name of option would be better: '-mdisable-dynshift-libcall' or '-mhw-shift'? Or if you want, please suggest another one. Thank you!