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
[(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>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>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>mode) - 1; i >= 0; --i)
+ for (int 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)
--- /dev/null
+/* { 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);
+}