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

Reply via email to