From: Georg-Johann Lay Date: Fri, 20 Feb 2015 10:30:24 +0000 (+0000) Subject: re PR target/64452 (ICE in avr-gcc when passing struct member to varargs function) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6b9861b12d076b262b86c69b1b5c30d779554384;p=gcc.git re PR target/64452 (ICE in avr-gcc when passing struct member to varargs function) gcc/ PR target/64452 * config/avr/avr.md (pushhi_insn): New insn. (push1): Push virtual regs in one chunk using pushhi1_insn. gcc/testsuite/ PR target/64452 * gcc.target/avr/torture/pr64452.c: New test. From-SVN: r220847 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff6df3df9f1..8d37e3534e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-02-20 Georg-Johann Lay + + PR target/64452 + * config/avr/avr.md (pushhi_insn): New insn. + (push1): Push virtual regs in one chunk using pushhi1_insn. + 2015-02-20 Bernd Schmidt Jakub Jelinek diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 5285a472e99..d6d930c74b6 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -371,6 +371,13 @@ push __zero_reg__" [(set_attr "length" "1,1")]) +(define_insn "pushhi1_insn" + [(set (mem:HI (post_dec:HI (reg:HI REG_SP))) + (match_operand:HI 0 "register_operand" "r"))] + "" + "push %B0\;push %A0" + [(set_attr "length" "2")]) + ;; All modes for a multi-byte push. We must include complex modes here too, ;; lest emit_single_push_insn "helpfully" create the auto-inc itself. (define_mode_iterator MPUSH @@ -386,17 +393,42 @@ [(match_operand:MPUSH 0 "" "")] "" { - int i; - - // Avoid (subreg (mem)) for non-generic address spaces below. Because - // of the poor addressing capabilities of these spaces it's better to - // load them in one chunk. And it avoids PR61443. - if (MEM_P (operands[0]) && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[0]))) - operands[0] = copy_to_mode_reg (mode, operands[0]); + { + // Avoid (subreg (mem)) for non-generic address spaces. Because + // of the poor addressing capabilities of these spaces it's better to + // load them in one chunk. And it avoids PR61443. + + operands[0] = copy_to_mode_reg (mode, operands[0]); + } + else if (REG_P (operands[0]) + && IN_RANGE (REGNO (operands[0]), FIRST_VIRTUAL_REGISTER, + LAST_VIRTUAL_REGISTER)) + { + // Byte-wise pushing of virtual regs might result in something like + // + // (set (mem:QI (post_dec:HI (reg:HI 32 SP))) + // (subreg:QI (plus:HI (reg:HI 28) + // (const_int 17)) 0)) + // + // after elimination. This cannot be handled by reload, cf. PR64452. + // Reload virtuals in one chunk. That way it's possible to reload + // above situation and finally + // + // (set (reg:HI **) + // (const_int 17)) + // (set (reg:HI **) + // (plus:HI (reg:HI **) + // (reg:HI 28))) + // (set (mem:HI (post_dec:HI (reg:HI 32 SP)) + // (reg:HI **))) + + emit_insn (gen_pushhi1_insn (operands[0])); + DONE; + } - for (i = GET_MODE_SIZE (mode) - 1; i >= 0; --i) + for (int i = GET_MODE_SIZE (mode) - 1; i >= 0; --i) { rtx part = simplify_gen_subreg (QImode, operands[0], mode, i); if (part != const0_rtx) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 62ae8d3c032..2409cfb0fa7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-02-20 Georg-Johann Lay + + PR target/64452 + * gcc.target/avr/torture/pr64452.c: New test. + 2015-02-19 Kaz Kojima * gcc.dg/tree-ssa/20040204-1.c: Don't XFAIL on sh*-*-*. diff --git a/gcc/testsuite/gcc.target/avr/torture/pr64452.c b/gcc/testsuite/gcc.target/avr/torture/pr64452.c new file mode 100644 index 00000000000..44cb2e057dd --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr64452.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c99" } */ + +struct A +{ + char str[8]; + void* v; +}; + +int varf (char* fmt, ...); + +void foo (struct A a, struct A b) +{ + varf ("%s%s", b.str, b.str); +} + +long long x64; + +void foo2 (long long j0, + struct A a, struct A b, struct A c, struct A d, + struct A e, struct A f, struct A g, struct A h, struct A i, + long long j1) +{ + varf ("%s%s", i.str, i.str, x64, j1+j0); +} + + +void foo3 (long long j0, + struct A a, struct A b, struct A c, struct A d, + struct A e, struct A f, struct A g, struct A h, struct A i, + long long j1) +{ + varf ("%s%s", &i.str, &b.str, x64, j1+j0); +}