[Bug target/92729] [avr] Convert the backend to MODE_CC so it can be kept in future releases

2020-11-30 Thread saaadhu at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92729

Senthil Kumar Selvaraj  changed:

   What|Removed |Added

 CC||saaadhu at gcc dot gnu.org

--- Comment #21 from Senthil Kumar Selvaraj  ---
FWIW, I was working on this as well some time in August, and had a semi working
implementation going. Pip's implementation generated better code on the few
benchmark workloads I compared, so I shelved my work
(https://github.com/saaadhu/gcc-avr-cc0/tree/avr-cc0-squashed)

I don't have the spare time now to start full fledged work on this, but I can
help with any issues you run into.

[Bug target/98762] New: Wrong code for avrtiny if source is Z and destination is R30 or R31

2021-01-20 Thread saaadhu at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98762

Bug ID: 98762
   Summary: Wrong code for avrtiny if source is Z and destination
is R30 or R31
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: target
  Assignee: unassigned at gcc dot gnu.org
  Reporter: saaadhu at gcc dot gnu.org
  Target Milestone: ---

avr_out_movqi_r_mr_reg_disp_tiny skips restoration of the base pointer reg pair
(using subi/sbci) if reg_overlap_mentioned_p or reg_unused_after returns true
for the pointer reg.

In the below case, (reg:HI 30) is the base reg, and (reg:QI 31) is the
destination. reg_overlap_mentioned_p (correctly) returns true, and therefore
*both* R30 and R31 are not restored to their original values, instead of just
R31. reg_unused_after also returns true for this case, as it also checks if
reg_overlap_mentioned_p for the current insn.

This causes miscompilation if the compiler later uses R30 with the assumption
that it is unmodified (which is what movqi_insn promises). In the below case
(reduced from execute/961122-1.c), the compiler only sets R31 again (with R19),
as it believes R30 is unmodified. 

Note that the bug is exposed if the splitter for HImode move to two QImode move
runs - otherwise, movhi_insn ensures both R30 and R31 are loaded again. 

$ cat reduced.c
long long acc;

void addhi (short a)
{
  acc += (long long) a << 32;
}

$ avr-gcc -mmcu=attiny40 -Os -dP -S reduce.c -o -

; (insn 53 52 264 (set (reg:QI 31 r31)
 ; (mem/c:QI (plus:HI (reg:HI 30 r30)
 ; (const_int 3 [0x3])) [1 acc+3 S1 A8])) "reduce.c":5:7 56
{movqi_insn}
 ;  (expr_list:REG_EQUAL (mem/c:QI (const:HI (plus:HI (symbol_ref:HI
("acc") [flags 0x2] )
 ; (const_int 3 [0x3]))) [1 acc+3 S1 A8])
 ; (nil)))
subi r30,lo8(-(3))   ;  53  [c=4 l=3]  movqi_insn/3
sbci r31,hi8(-(3))
ld r31,Z
 ; (insn 264 53 296 (set (mem/c:QI (plus:HI (reg/f:HI 28 r28)
 ; (const_int 16 [0x10])) [3 %sfp+16 S1 A8])
 ; (reg:QI 31 r31)) "reduce.c":5:7 56 {movqi_insn}
 ;  (expr_list:REG_DEAD (reg:QI 31 r31)
 ; (nil)))
subi r28,lo8(-(16))  ;  264 [c=4 l=5]  movqi_insn/2
sbci r29,hi8(-(16))
st Y,r31
subi r28,lo8((16))
sbci r29,hi8((16))
 ; (insn 296 264 54 (set (reg:QI 31 r31 [+1 ])
 ; (reg:QI 19 r19 [+1 ])) "reduce.c":5:7 56 {movqi_insn}
 ;  (nil))
mov r31,r19  ;  296 [c=4 l=1]  movqi_insn/0
 ; (insn 54 296 266 (set (reg:QI 31 r31)
 ; (mem/c:QI (plus:HI (reg:HI 30 r30)
 ; (const_int 4 [0x4])) [1 acc+4 S1 A8])) "reduce.c":5:7 56
{movqi_insn}
 ;  (expr_list:REG_EQUAL (mem/c:QI (const:HI (plus:HI (symbol_ref:HI
("acc") [flags 0x2] )
 ; (const_int 4 [0x4]))) [1 acc+4 S1 A8])
 ; (nil)))
subi r30,lo8(-(4))   ;  54  [c=4 l=3]  movqi_insn/3
sbci r31,hi8(-(4))
ld r31,Z
 ; (insn 266 54 298 (set (mem/c:QI (plus:HI (reg/f:HI 28 r28)
 ; (const_int 17 [0x11])) [3 %sfp+17 S1 A8])
 ; (reg:QI 31 r31)) "reduce.c":5:7 56 {movqi_insn}
 ;  (expr_list:REG_DEAD (reg:QI 31 r31)
 ; (nil)))
subi r28,lo8(-(17))  ;  266 [c=4 l=5]  movqi_insn/2
sbci r29,hi8(-(17))
st Y,r31

[Bug target/92729] [avr] Convert the backend to MODE_CC so it can be kept in future releases

2021-02-06 Thread saaadhu at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92729

--- Comment #48 from Senthil Kumar Selvaraj  ---
Submitted https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563638.html,
which addresses comments made when the work-in-progress version was submitted.
There are no regression failures (save for some tests that fail because of code
size increase) on atmega128, atxmega128a3, attiny40 and atmega8. 

Follow up patch
https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563779.html improves
code size regressions. More patches along the way - fixing some define_splits,
and adding CC_CZN and CC_ZN modes, along with enabling the cmpelim pass.

[Bug target/92729] [avr] Convert the backend to MODE_CC so it can be kept in future releases

2021-04-30 Thread saaadhu at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92729

Senthil Kumar Selvaraj  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|NEW |RESOLVED

--- Comment #49 from Senthil Kumar Selvaraj  ---
Both the above patches (rebased against latest master) are now committed.

See https://gcc.gnu.org/pipermail/gcc-patches/2021-April/568658.html and
https://gcc.gnu.org/pipermail/gcc-patches/2021-April/569253.html.

There's more work to be done to improve code gen (as described in
https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563638.html), and I
intend to work on those items in my spare time.

[Bug target/101188] [AVR] Miscompilation and function pointers

2021-06-25 Thread saaadhu at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101188

Senthil Kumar Selvaraj  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
 CC||saaadhu at gcc dot gnu.org
 Ever confirmed|0   |1
   Last reconfirmed||2021-06-25

--- Comment #1 from Senthil Kumar Selvaraj  ---
Confirmed with 12.0.0 20210625

Here's a reduced testcase that hangs indefinitely with avrtest - the log shows
call to address 0.

$ cat fail.c
#include 
#include 

typedef uint8_t (*fn1)(void *a);
typedef void (*fn2)(void *a, const uint32_t *arg);

struct S {
uint8_t buffer[64];
uint16_t n;
fn2 f2;
void *a;
fn1 f1;
};

volatile uint16_t x;
void __attribute__((noinline))
foo(uint16_t n)
{
  x = n;
}

void __attribute__((noinline)) testfn(struct S *self)
{
uint32_t arg;

foo(self->n);
self->n++;
self->f2(self->a, &arg);
self->buffer[0] = self->f1(self->a);
}

static unsigned char myfn2_called = 0;
static void
myfn2(void *a, const uint32_t * arg)
{
  myfn2_called = 1;  
}

static uint8_t
myfn1(void *a)
{ }

int main() {
  struct S s;
  s.n = 0; s.f2 = myfn2; s.f1 = myfn1;
  testfn(&s);
  if (myfn2_called != 1)
abort();
  return 0;
}

$ avr-gcc -mmcu=atmega128 fail.c -O2 ~/code/avrtest/exit-atmega128.o --version
avr-gcc (GCC) 12.0.0 20210625 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ~/code/avrtest/avrtest -mmcu=avr51 a.out 
^C

The below code is at fault - there's an ldi to r31, followed by a load to Z
using R31:R30, and then an icall. The clobbering of r31 at 0x138 causes junk
values (0) to be read into Z, and icall calls address 0. 

 138:   f4 e4   ldi r31, 0x44   ; 68
 13a:   ef 0e   add r14, r31
 13c:   f1 1c   adc r15, r1
 13e:   32 96   adiwr30, 0x02   ; 2
 140:   01 90   ld  r0, Z+
 142:   f0 81   ld  r31, Z
 144:   e0 2d   mov r30, r0
 146:   be 01   movwr22, r28
 148:   6f 5f   subir22, 0xFF   ; 255
 14a:   7f 4f   sbcir23, 0xFF   ; 255
 14c:   d7 01   movwr26, r14
 14e:   8d 91   ld  r24, X+
 150:   9c 91   ld  r25, X
 152:   09 95   icall