GCC-SH: bug in force_to_mode()

Toshi Morita tm2@best.com
Sun Feb 25 13:21:00 GMT 2001


version: GCC CVS 2/23/2001 & gcc-2.95.2
   host: i386-linux
 target: sh-elf

I've found a bug in force_to_mode() in combine.c.

The bug occurs when simplify_logical() is called for SImode, with reg:SI 57
known to contain 0:

(gdb) 
simplify_logical (x=0x8289138, last=0) at combine.c:4912
4912              if (last
(gdb) 
4907              x = simplify_and_const_int (x, mode, op0, INTVAL (op1));
(gdb) call debug_rtx(x)

(and:SI (plus:SI (reg/v:SI 57)
        (const_int 23 [0x17]))
    (const_int 60 [0x3c]))
(gdb) next
4912              if (last
(gdb) call debug_rtx(x)

(const_int 23 [0x17])
(gdb) 

simplify_logical() winds up calling a few things, and eventually winds up
in force_to_mode():

(gdb) bt
#0  force_to_mode (x=0x82890c8, mode=SImode, mask=4294967295, reg=0x0, 
    just_select=0) at combine.c:6493
#1  0x81525d3 in simplify_and_const_int (x=0x8289138, mode=SImode, 
    varop=0x82890c8, constop=60) at combine.c:7322
#2  0x814e945 in simplify_logical (x=0x8289138, last=0) at combine.c:4907

The bug occurs because of this code in force_to_mode():

  /* When we have an arithmetic operation, or a shift whose count we
     do not know, we need to assume that all bit the up to the highest-order
     bit in MASK will be needed.  This is how we form such a mask.  */
  if (op_mode)
    fuller_mask = (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT
                   ? GET_MODE_MASK (op_mode)
                   : ((HOST_WIDE_INT) 1 << (floor_log2 (mask) + 1)) - 1);
  else
    fuller_mask = ~ (HOST_WIDE_INT) 0;
...
    case MINUS:
    case MULT:
      /* For PLUS, MINUS and MULT, we need any bits less significant than the
         most significant bit in MASK since carries from those bits will
         affect the bits we are interested in.  */
      mask = fuller_mask;
      goto binop;

This code appears to be needed because ((A + B) & C) != (A & C) + (B & C)
because the low-order bits may affect the result. This is fine, but
the original mask is never applied because the mask = fuller_mask; is
executed and the original mask has been overwritten!

How should this be fixed? Should simplify_and_const_int not be calling
force_to_mode?

Toshi




More information about the Gcc-bugs mailing list