This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
reg-stack and complex return value
- To: rth at cygnus dot com, gcc-patches at gcc dot gnu dot org, patches at x86-65 dot org
- Subject: reg-stack and complex return value
- From: Jan Hubicka <jh at suse dot cz>
- Date: Thu, 3 May 2001 18:48:56 +0200
Hi
This appears to be all changes needed to get complex return values working
in reg-stack.c
Most trickery comes from the part that when returning, we may have live just
half of the value. Also handling of clobbers needs updating, since these
never get to reg-stack usually, because they are elliminated in flow,
but they can't for register halves.
Honza
Thu May 3 18:45:30 CEST 2001 Jan Hubicka <jh@suse.cz>
* reg-stack.c (emit_pop_insn): Pop both halves of complex number
(subst_stack_regs_pat): Push the second register to stack if needed.
(subst_stack_regs): Avoid processing of clobber with REG_UNUSED note.
(convert_regs_exit): Convert registers in reversed order to get
them properly pushed.
*** /home/hubicka/egcs/gcc/reg-stack.c Tue May 1 14:59:26 2001
--- reg-stack.c Thu May 3 18:19:02 2001
*************** emit_pop_insn (insn, regstack, reg, wher
*** 937,942 ****
--- 937,959 ----
return pop_insn;
}
+ /* For complex types take care to pop both halves. These may survive in
+ CLOBBER and USE expressions. */
+ if (COMPLEX_MODE_P (GET_MODE (reg)))
+ {
+ rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
+ rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
+
+ pop_insn = NULL_RTX;
+ if (get_hard_regnum (regstack, reg1) >= 0)
+ pop_insn = emit_pop_insn (insn, regstack, reg1, where);
+ if (get_hard_regnum (regstack, reg2) >= 0)
+ pop_insn = emit_pop_insn (insn, regstack, reg2, where);
+ if (!pop_insn)
+ abort ();
+ return pop_insn;
+ }
+
hard_regno = get_hard_regnum (regstack, reg);
if (hard_regno < FIRST_STACK_REG)
*************** subst_stack_regs_pat (insn, regstack, pa
*** 1468,1478 ****
}
else
{
! /* A top-level clobber with no REG_DEAD, and no hard-regnum
! indicates an uninitialized value. Because reload removed
! all other clobbers, this must be due to a function
! returning without a value. Load up a NaN. */
if (! note
&& get_hard_regnum (regstack, *dest) == -1)
{
--- 1485,1506 ----
}
else
{
! /* A top-level clobber with no REG_DEAD nor REG_UNUSED,
! and no hard-regnum indicates an uninitialized value.
! Because reload removed all other clobbers, this must
! be due to a function returning without a value. Load
! up a NaN. */
+ if (! note && COMPLEX_MODE_P (GET_MODE (*dest))
+ && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest) + 1,
+ DFmode)) == -1)
+ {
+ pat = gen_rtx_SET (VOIDmode,
+ FP_MODE_REG (REGNO (*dest) + 1, SFmode),
+ nan);
+ insn = emit_insn_before (pat, insn);
+ move_for_stack_reg (emit_insn_before (pat, insn), regstack, pat);
+ }
if (! note
&& get_hard_regnum (regstack, *dest) == -1)
{
*************** subst_stack_regs (insn, regstack)
*** 2154,2159 ****
--- 2182,2205 ----
}
}
+ /* Clobber with REG_UNUSED note may not have register alive previously.
+ Handle it early, otherwise we will emit dumy load and pop of the
+ register. */
+ if (GET_CODE (PATTERN (insn)) == CLOBBER)
+ {
+ rtx dest = *get_true_reg (&XEXP (PATTERN (insn), 0));
+ note = find_reg_note (insn, REG_UNUSED, dest);
+ if (note && get_hard_regnum (regstack, dest) == -1
+ && (!COMPLEX_MODE_P (GET_MODE (dest))
+ || get_hard_regnum (regstack, FP_MODE_REG (REGNO (dest) + 1,
+ DFmode)) == -1))
+ {
+ delete_insn_for_stacker (insn);
+ return;
+ }
+
+ }
+
/* Do the actual substitution if any stack regs are mentioned.
Since we only record whether entire insn mentions stack regs, and
subst_stack_regs_pat only works for patterns that contain stack regs,
*************** convert_regs_exit ()
*** 2440,2446 ****
output_stack->top = value_reg_high - value_reg_low;
for (reg = value_reg_low; reg <= value_reg_high; ++reg)
{
! output_stack->reg[reg - value_reg_low] = reg;
SET_HARD_REG_BIT (output_stack->reg_set, reg);
}
}
--- 2486,2492 ----
output_stack->top = value_reg_high - value_reg_low;
for (reg = value_reg_low; reg <= value_reg_high; ++reg)
{
! output_stack->reg[value_reg_high - reg] = reg;
SET_HARD_REG_BIT (output_stack->reg_set, reg);
}
}