Dang, forgot to add gcc-patches... -------- Original Message -------- Subject: [AVR] Fix PR49881 Date: Mon, 01 Aug 2011 11:58:32 -0700 From: Richard Henderson <r...@redhat.com> To: Denis Chertykov <cherty...@gmail.com>, eric.wedding...@atmel.com CC: a...@gjlay.de
The following iteration fixes the two regressions reported in comment 7 of the PR. These were ICEs due to emit_push_insn_single being "helpful" with pushing complex numbers. Instead of recursing for the components of a complex number, it simply generated raw pre_dec patterns. This is arguably a middle-end bug, but it's easier to fix in the backend by listing complex modes in the macro for the push expander. Ok? r~
* config/avr/avr.h (PUSH_ROUNDING): New. * config/avr/avr.md (pushqi1): Rename from *pushqi. (*pushhi, *pushsi, *pushsf): Remove. (MPUSH): New mode iterator. (push<MPUSH>1): New expander. diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index ddd30d6..6a80693 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -665,3 +665,7 @@ struct GTY(()) machine_function /* 'true' if a callee might be tail called */ int sibcall_fails; }; + +/* AVR does not round pushes, but the existance of this macro is + required in order for pushes to be generated. */ +#define PUSH_ROUNDING(X) (X) diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 55a883e..f60f9f0 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -202,8 +202,7 @@ DONE; }) - -(define_insn "*pushqi" +(define_insn "pushqi1" [(set (mem:QI (post_dec:HI (reg:HI REG_SP))) (match_operand:QI 0 "reg_or_0_operand" "r,L"))] "" @@ -212,33 +211,29 @@ push __zero_reg__" [(set_attr "length" "1,1")]) -(define_insn "*pushhi" - [(set (mem:HI (post_dec:HI (reg:HI REG_SP))) - (match_operand:HI 0 "reg_or_0_operand" "r,L"))] - "" - "@ - push %B0\;push %A0 - push __zero_reg__\;push __zero_reg__" - [(set_attr "length" "2,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 + [(CQI "") + (HI "") (CHI "") + (SI "") (CSI "") + (DI "") (CDI "") + (SF "") (SC "")]) -(define_insn "*pushsi" - [(set (mem:SI (post_dec:HI (reg:HI REG_SP))) - (match_operand:SI 0 "reg_or_0_operand" "r,L"))] +(define_expand "push<mode>1" + [(match_operand:MPUSH 0 "general_operand" "")] "" - "@ - push %D0\;push %C0\;push %B0\;push %A0 - push __zero_reg__\;push __zero_reg__\;push __zero_reg__\;push __zero_reg__" - [(set_attr "length" "4,4")]) - -(define_insn "*pushsf" - [(set (mem:SF (post_dec:HI (reg:HI REG_SP))) - (match_operand:SF 0 "register_operand" "r"))] - "" - "push %D0 - push %C0 - push %B0 - push %A0" - [(set_attr "length" "4")]) +{ + int i; + for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i) + { + rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i); + if (part != const0_rtx) + part = force_reg (QImode, part); + emit_insn (gen_pushqi1 (part)); + } + DONE; +}) ;;======================================================================== ;; move byte