------- Additional Comments From dmixm at marine dot febras dot ru 2004-11-16 23:58 ------- In March, 2004 Richard Sandiford has offered a patch for elimination of this problem. See: http://gcc.gnu.org/ml/gcc/2004-03/msg01456.html This patch modifies function do_jump (a file dojump.c). This change now is present at a branch 4.0, but does not enter in 3.4.x. I have tried to apply this patch to 3.4.3. It has earned only after change of a line if (TREE_CODE (TREE_OPERAND (exp, 0)) == RSHIFT_EXPR ... to tree arg_nops = TREE_OPERAND (exp, 0); /* and below the same subst. */ STRIP_NOPS (arg_nops); if (TREE_CODE (arg_nops) == RSHIFT_EXPR ... and only for function foo_i. foo_i() before patch: ... mov r24,r25 ldi r25,6 1: lsr r24 dec r25 brne 1b sbrs r24,0 rjmp .L2 foo_i() after patch: ... sbrs r25,6 rjmp .L8 But foo_ll (shift loop with count 62!) and foo_l have remained on old - through shift of the left argument. Source file: ~~~~~~~~~~~ int foo_ll (long long x) { return (x & 0x4000000000000000LL) ? 1 : 3; } int foo_l (long x) { return (x & 0x40000000) ? 5 : 7; } int foo_i (int x) { return (x & 0x4000) ? 9 : 11; } int foo_c (char x) { return (x & 0x40) ? 13 : 15; } P.S. The code for foo_c was and remains beautiful due to work `gcc/combine.c' .
-- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18424