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

Reply via email to