From: Georg-Johann Lay Date: Fri, 20 Feb 2015 11:15:56 +0000 (+0000) Subject: backport: re PR target/64452 (ICE in avr-gcc when passing struct member to varargs... X-Git-Tag: releases/gcc-4.8.5~262 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c35497b3711f272215eae4dc38d37539235d2631;p=thirdparty%2Fgcc.git backport: re PR target/64452 (ICE in avr-gcc when passing struct member to varargs function) gcc/ Backport from 2015-02-20 trunk r220847. PR target/64452 * config/avr/avr.md (pushhi_insn): New insn. (push1): Push virtual regs in one chunk using pushhi1_insn. gcc/testsuite/ Backport from 2015-02-20 trunk r220847. PR target/64452 * gcc.target/avr/torture/pr64452.c: New test. From-SVN: r220849 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21031e2e864c..c1f5e8d70ecd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-02-20 Georg-Johann Lay + + Backport from 2015-02-20 trunk r220847. + + PR target/64452 + * config/avr/avr.md (pushhi_insn): New insn. + (push1): Push virtual regs in one chunk using pushhi1_insn. + 2015-02-20 Uros Bizjak Backport from mainline diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index f56008bf4362..5a38e798886c 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -351,6 +351,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 @@ -366,17 +373,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 4b9ca6c93988..c9c7c836de6e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-02-20 Georg-Johann Lay + + Backport from 2015-02-20 trunk r220847. + + PR target/64452 + * gcc.target/avr/torture/pr64452.c: New test. + 2015-02-20 Uros Bizjak Backport from mainline 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 000000000000..44cb2e057ddc --- /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); +}