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))