Deadly optimization bug (all gcc versions!)

Franz Sirl Franz.Sirl-kernel@lauterbach.com
Wed Aug 18 14:07:00 GMT 1999


Am Mit, 18 Aug 1999 schrieb Franz Sirl:
>This IF_THEN_ELSE doesn't look right to me. I'll continue debugging tomorrow,
>it's already too late here :-).

OK, it really happens in this code around line 6927 in if_then_else_cond():

  /* Likewise for 0 or a single bit.  */
  else if (exact_log2 (nz = nonzero_bits (x, mode)) >= 0)
    {
      *ptrue = GEN_INT (nz), *pfalse = const0_rtx;
      return x;
    }

nonzero_bits() calls get_last_value() on x with subst_low_cuid pointing to insn
14:

(insn 11 10 14 (parallel[
            (set (reg/v:SI 84)
                (and:SI (reg:SI 4 r4)
                    (const_int 1 [0x1])))
            (clobber (scratch:CC))
        ] ) 121 {andsi3} (nil)
    (expr_list:REG_DEAD (reg:SI 4 r4)
        (expr_list:REG_UNUSED (scratch:CC)
            (nil))))

(insn 14 11 17 (set (reg/v:SI 85)
        (lshiftrt:SI (reg:SI 3 r3)
            (const_int 1 [0x1]))) 211 {lshrsi3_no_power} (nil)
    (expr_list:REG_DEAD (reg:SI 3 r3)
        (nil)))


This means that nonzero_bits() will operate on insn 11 (which is returned by
get_last_value) and return 1. However, it should return 3 for insn 17, as was
the case before subst_low_cuid was lowered to insn 14 during the substition
processing.

(insn 17 14 20 (set (reg/v:SI 84)
        (plus:SI (reg/v:SI 84)
            (const_int 1 [0x1]))) 52 {*addsi3_internal1} (insn_list 11 (nil))
    (nil))

(insn 20 17 22 (set (reg:SI 87)
        (lshiftrt:SI (reg/v:SI 84)
            (const_int 1 [0x1]))) 211 {lshrsi3_no_power} (insn_list 17 (nil))
    (expr_list:REG_DEAD (reg/v:SI 84)
        (nil)))

(insn 22 20 24 (set (reg:SI 86)
        (plus:SI (reg/v:SI 85)
            (reg:SI 87))) 52 {*addsi3_internal1} (insn_list 14 (insn_list 20 (nil)))
    (expr_list:REG_DEAD (reg/v:SI 85)
        (expr_list:REG_DEAD (reg:SI 87)
            (nil))))

Well, this is the analysis, however I have no idea how to fix it correctly :-(.
A local fix in if_then_else_cond() would be to compare the results of
nonzero_bits(x), reg_nonzero_bits[REGNO(x)] and
reg_last_set_nonzero_bits[REGNO(x)] and use the biggest one? But this may
just hide other potential problems with get_last_value()?

Franz.


More information about the Gcc mailing list