This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/36609] New: AVR wrong code using incorrect RTL for test reversal pattern
- From: "hutchinsonandy at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 23 Jun 2008 22:52:25 -0000
- Subject: [Bug target/36609] New: AVR wrong code using incorrect RTL for test reversal pattern
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
I found problem with AVR test instructions such used by c/c++ code (x>0)
and demonstrated by testsuite test gcc.c-torture/execute/pr22493-1.c
#include <limits.h>
extern void abort ();
extern void exit (int);
void f(int i)
{
if (i>0)
abort();
i = -i;
if (i<0)
return;
abort ();
}
int main(int argc, char *argv[])
{
f(INT_MIN);
exit (0);
}
Compiling this with:
avr-gcc -c -mmcu=atmega128 -I. -w -Os -fwrapv -mmcu=atmega128 -Wall
-Wstrict-prototypes -Wa,-ahlms=test.s -std=gnu99 test.c -o test.o
produces wrong code.
An integer test x>0 is translated into RTL:
CC0=Rx
from which we create AVR assembler code
TST Rx
which is equivalent to CMP Rx,0
AVR target also have negated_tst RTL patterns to reverse tests in avr_reorg so
that we can match the available branches on AVR. For example AVR has BRLT and
BRGE but not BRLE and BRGT.
So
CC0 = Rx
Jump LE
becomes reorganized as
CC0 = NEG:xx(Rx)
Jump GE
which emits the following code via define_insn "*negated_tst.....
CMP 0,Rx
BRGE
For such test reversals the final code is correct. However, the intermediate
RTL used by translation is WRONG
CC0=Rx
Jump LE
is NOT equivalent to
CC0 = NEG:xx(Rx)
Jump GE
For test reversal the problem is hidden - 2 wrongs making a right in this case.
BUT the bug appears when we have a normal code sequence such as
NEG:xx(Rx)
CC0 = Rx
which the combine phase will match against the RTL of *negated_tst and result
in assembler code of:
CMP 0,Rx
which is incorrect. Consider the case where Rx= -32768
NEG:HI(-32768) => -32768
CC0 = -32768 => Negative correct!
but the replacment:
CMP 0,-32768 =>Positive - WRONG
The fix is to redefine the "*negated_tst" RTL patterns to use correct COMPARES
and have avr_reorg to emit the corrected RTL.
(define_insn "*reversed_tsthi"
[(set (cc0)
(compare (const_int 0)
(match_operand:HI 0 "register_operand" "r")))
Test reversals will be unaffected. But now combine won't find any bad RTL.
I have not studied to see if the above RTL is ever generated. If it is, it is
perfectly safe.
--
Summary: AVR wrong code using incorrect RTL for test reversal
pattern
Product: gcc
Version: 4.4.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: hutchinsonandy at gcc dot gnu dot org
GCC build triplet: i686-pc-cygwin
GCC host triplet: i686-pc-cygwin
GCC target triplet: avr-unknown-none
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36609