http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54330

             Bug #: 54330
           Summary: Wrong optimization for code from fixed-bit.c
    Classification: Unclassified
           Product: gcc
           Version: 4.8.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: other
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: g...@gcc.gnu.org
              Host: i686-pc-linux-gnu
            Target: avr
             Build: i686-pc-linux-gnu


Created attachment 28056
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=28056
fixed-bit-bug.c: preprocessed bit for fixed.bit.c::__satfractudadq

This is a wrong code bug seen while implementing the ISO/IED TR18037
fixed-point support for AVR.

== compile ==

$ avr-gcc fixed-bit-bug.c -mmcu=atmega128 -Os -S -fdump-rtl-expand-details

== configure ==

$ ../../gcc.gnu.org/trunk/configure --target=avr
--prefix=/local/gnu/install/gcc-4.8 --disable-nls --with-dwarf2
--enable-target-optspace=yes --enable-languages=c,c++

== Bug ==

The .expand dump contains a wrong insn, a GTU branch instead of a LEU branch:

The code tests if the high bit of a shift result is set by comparing >
0x7fffffffffffffff. If the value is less-or-equal, the saturation against 0
must be skipped (goto #76), but the GTU leads to a reversal of the condition. 
The block that saturates is BB6:

(insn 104 103 105 5 (parallel [
            (set (cc0)
                (compare (reg:DI 18 r18)
                    (const_double -1 [0xffffffff] 2147483647 [0x7fffffff] 0 [0]
0 [0] 0 [0] 0 [0])))
            (clobber (scratch:QI))
        ]) fixed-bit-bug.c:56 -1
     (nil))
(jump_insn 105 104 132 5 (set (pc)
        (if_then_else (gtu (cc0)
                (const_int 0 [0]))
            (label_ref 76)
            (pc))) fixed-bit-bug.c:56 -1
     (expr_list:REG_BR_PROB (const_int 6100 [0x17d4])
        (nil))
 -> 76)
(note 132 105 29 6 [bb 6] NOTE_INSN_BASIC_BLOCK)
(insn 29 132 21 6 (clobber (reg/v:DI 42 [ low ])) fixed-bit-bug.c:56 -1
     (nil))
(insn 21 29 22 6 (set (subreg:QI (reg/v:DI 42 [ low ]) 0)
        (const_int 0 [0])) fixed-bit-bug.c:56 -1
     (nil))


All of the following changes lead to correct code, u.e. LEU instead of GTU:

* -O1 instead of -O0

* -fno-builtin-memcpy

* Using DI mode instead of DQ resp. DA mode, see the respective #define in the
attaches test case.

Correct code will look like that:

(jump_insn 91 90 132 4 (set (pc)
        (if_then_else (leu (cc0)
                (const_int 0 [0]))
            (label_ref:HI 102)
            (pc))) 444 {difficult_branch}
     (expr_list:REG_BR_PROB (const_int 5000 [0x1388])
        (nil))
 -> 102)
(note 132 91 100 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
(insn 100 132 92 5 (clobber (reg/v:DI 42 [ low ])) -1
     (nil))
(insn 92 100 93 5 (set (subreg:QI (reg/v:DI 42 [ low ]) 0)
        (const_int -1 [0xffffffff])) -1
     (nil))

Reply via email to