diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-12-13 02:32:06 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-12-13 02:32:06 +0000 |
commit | 99f4aa936d031cd7642e433a399a4eca2654d3d5 (patch) | |
tree | 5070814a21016136d25e836352ef412330dfe833 /gcc/reg-stack.c | |
parent | 2b2d3dc00ca03920672fa7669d97bb0ad40572dc (diff) | |
download | gcc-99f4aa936d031cd7642e433a399a4eca2654d3d5.tar.gz |
PR rtl-opt/17186
* reg-stack.c (move_nan_for_stack_reg): New.
(subst_stack_regs_pat): Use it.
(move_for_stack_reg): Handle source register not live with a nan.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92073 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r-- | gcc/reg-stack.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 5ec8ba5b1b4..d561416fa2c 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -251,6 +251,7 @@ static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where); static void emit_swap_insn (rtx, stack, rtx); static void swap_to_top(rtx, stack, rtx, rtx); static bool move_for_stack_reg (rtx, stack, rtx); +static bool move_nan_for_stack_reg (rtx, stack, rtx); static int swap_rtx_condition_1 (rtx); static int swap_rtx_condition (rtx); static void compare_for_stack_reg (rtx, stack, rtx); @@ -1055,10 +1056,14 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat) if (regstack->reg[i] == REGNO (src)) break; - /* The source must be live, and the dest must be dead. */ - gcc_assert (i >= 0); + /* The destination must be dead, or life analysis is borked. */ gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG); + /* If the source is not live, this is yet another case of + uninitialized variables. Load up a NaN instead. */ + if (i < 0) + return move_nan_for_stack_reg (insn, regstack, dest); + /* It is possible that the dest is unused after this insn. If so, just pop the src. */ @@ -1159,6 +1164,22 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat) return control_flow_insn_deleted; } + +/* A helper function which replaces INSN with a pattern that loads up + a NaN into DEST, then invokes move_for_stack_reg. */ + +static bool +move_nan_for_stack_reg (rtx insn, stack regstack, rtx dest) +{ + rtx pat; + + dest = FP_MODE_REG (REGNO (dest), SFmode); + pat = gen_rtx_SET (VOIDmode, dest, not_a_num); + PATTERN (insn) = pat; + INSN_CODE (insn) = -1; + + return move_for_stack_reg (insn, regstack, pat); +} /* Swap the condition on a branch, if there is one. Return true if we found a condition to swap. False if the condition was not used as @@ -1430,23 +1451,19 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) 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) - { - pat = gen_rtx_SET (VOIDmode, - FP_MODE_REG (REGNO (*dest), SFmode), - not_a_num); - PATTERN (insn) = pat; - control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat); - } - if (! note && COMPLEX_MODE_P (GET_MODE (*dest)) - && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1) + if (!note) { - pat = gen_rtx_SET (VOIDmode, - FP_MODE_REG (REGNO (*dest) + 1, SFmode), - not_a_num); - PATTERN (insn) = pat; - control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat); + rtx t = *dest; + if (get_hard_regnum (regstack, t) == -1) + control_flow_insn_deleted + |= move_nan_for_stack_reg (insn, regstack, t); + if (COMPLEX_MODE_P (GET_MODE (t))) + { + t = FP_MODE_REG (REGNO (t) + 1, DFmode); + if (get_hard_regnum (regstack, t) == -1) + control_flow_insn_deleted + |= move_nan_for_stack_reg (insn, regstack, t); + } } } } @@ -2921,13 +2938,9 @@ convert_regs_1 (FILE *file, basic_block block) rtx set; if (file) - { - fprintf (file, "Emitting insn initializing reg %d\n", - reg); - } + fprintf (file, "Emitting insn initializing reg %d\n", reg); - set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode), - not_a_num); + set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode), not_a_num); insn = emit_insn_after (set, insn); control_flow_insn_deleted |= subst_stack_regs (insn, ®stack); } |