diff options
author | kan <kan@FreeBSD.org> | 2004-07-28 03:11:36 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2004-07-28 03:11:36 +0000 |
commit | 5e00ec74d8ce58f99801200d4d3d0412c7cc1b28 (patch) | |
tree | 052f4bb635f2bea2c5e350bd60c902be100a0d1e /contrib/gcc/reg-stack.c | |
parent | 87b8398a7d9f9bf0e28bbcd54a4fc27db2125f38 (diff) | |
download | FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.zip FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.tar.gz |
Gcc 3.4.2 20040728.
Diffstat (limited to 'contrib/gcc/reg-stack.c')
-rw-r--r-- | contrib/gcc/reg-stack.c | 416 |
1 files changed, 224 insertions, 192 deletions
diff --git a/contrib/gcc/reg-stack.c b/contrib/gcc/reg-stack.c index 8e6731b..9a6c89b 100644 --- a/contrib/gcc/reg-stack.c +++ b/contrib/gcc/reg-stack.c @@ -1,6 +1,6 @@ /* Register to Stack convert for GNU compiler. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -153,6 +153,8 @@ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "rtl.h" #include "tm_p.h" @@ -234,45 +236,41 @@ static rtx nan; /* Forward declarations */ -static int stack_regs_mentioned_p PARAMS ((rtx pat)); -static void straighten_stack PARAMS ((rtx, stack)); -static void pop_stack PARAMS ((stack, int)); -static rtx *get_true_reg PARAMS ((rtx *)); - -static int check_asm_stack_operands PARAMS ((rtx)); -static int get_asm_operand_n_inputs PARAMS ((rtx)); -static rtx stack_result PARAMS ((tree)); -static void replace_reg PARAMS ((rtx *, int)); -static void remove_regno_note PARAMS ((rtx, enum reg_note, - unsigned int)); -static int get_hard_regnum PARAMS ((stack, rtx)); -static rtx emit_pop_insn PARAMS ((rtx, stack, rtx, - enum emit_where)); -static void emit_swap_insn PARAMS ((rtx, stack, rtx)); -static void move_for_stack_reg PARAMS ((rtx, stack, rtx)); -static int swap_rtx_condition_1 PARAMS ((rtx)); -static int swap_rtx_condition PARAMS ((rtx)); -static void compare_for_stack_reg PARAMS ((rtx, stack, rtx)); -static void subst_stack_regs_pat PARAMS ((rtx, stack, rtx)); -static void subst_asm_stack_regs PARAMS ((rtx, stack)); -static void subst_stack_regs PARAMS ((rtx, stack)); -static void change_stack PARAMS ((rtx, stack, stack, - enum emit_where)); -static int convert_regs_entry PARAMS ((void)); -static void convert_regs_exit PARAMS ((void)); -static int convert_regs_1 PARAMS ((FILE *, basic_block)); -static int convert_regs_2 PARAMS ((FILE *, basic_block)); -static int convert_regs PARAMS ((FILE *)); -static void print_stack PARAMS ((FILE *, stack)); -static rtx next_flags_user PARAMS ((rtx)); -static void record_label_references PARAMS ((rtx, rtx)); -static bool compensate_edge PARAMS ((edge, FILE *)); +static int stack_regs_mentioned_p (rtx pat); +static void straighten_stack (rtx, stack); +static void pop_stack (stack, int); +static rtx *get_true_reg (rtx *); + +static int check_asm_stack_operands (rtx); +static int get_asm_operand_n_inputs (rtx); +static rtx stack_result (tree); +static void replace_reg (rtx *, int); +static void remove_regno_note (rtx, enum reg_note, unsigned int); +static int get_hard_regnum (stack, rtx); +static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where); +static void emit_swap_insn (rtx, stack, rtx); +static bool move_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); +static bool subst_stack_regs_pat (rtx, stack, rtx); +static void subst_asm_stack_regs (rtx, stack); +static bool subst_stack_regs (rtx, stack); +static void change_stack (rtx, stack, stack, enum emit_where); +static int convert_regs_entry (void); +static void convert_regs_exit (void); +static int convert_regs_1 (FILE *, basic_block); +static int convert_regs_2 (FILE *, basic_block); +static int convert_regs (FILE *); +static void print_stack (FILE *, stack); +static rtx next_flags_user (rtx); +static void record_label_references (rtx, rtx); +static bool compensate_edge (edge, FILE *); /* Return nonzero if any stack register is mentioned somewhere within PAT. */ static int -stack_regs_mentioned_p (pat) - rtx pat; +stack_regs_mentioned_p (rtx pat) { const char *fmt; int i; @@ -301,8 +299,7 @@ stack_regs_mentioned_p (pat) /* Return nonzero if INSN mentions stacked registers, else return zero. */ int -stack_regs_mentioned (insn) - rtx insn; +stack_regs_mentioned (rtx insn) { unsigned int uid, max; int test; @@ -334,13 +331,12 @@ stack_regs_mentioned (insn) static rtx ix86_flags_rtx; static rtx -next_flags_user (insn) - rtx insn; +next_flags_user (rtx insn) { /* Search forward looking for the first use of this value. Stop at block boundaries. */ - while (insn != current_block->end) + while (insn != BB_END (current_block)) { insn = NEXT_INSN (insn); @@ -357,9 +353,7 @@ next_flags_user (insn) after this insn. */ static void -straighten_stack (insn, regstack) - rtx insn; - stack regstack; +straighten_stack (rtx insn, stack regstack) { struct stack_def temp_stack; int top; @@ -382,9 +376,7 @@ straighten_stack (insn, regstack) /* Pop a register from the stack. */ static void -pop_stack (regstack, regno) - stack regstack; - int regno; +pop_stack (stack regstack, int regno) { int top = regstack->top; @@ -414,10 +406,8 @@ pop_stack (regstack, regno) code duplication created when the converter inserts pop insns on the edges. */ -void -reg_to_stack (first, file) - rtx first; - FILE *file; +bool +reg_to_stack (rtx first, FILE *file) { basic_block bb; int i; @@ -432,11 +422,15 @@ reg_to_stack (first, file) if (regs_ever_live[i]) break; if (i > LAST_STACK_REG) - return; + return false; /* Ok, floating point instructions exist. If not optimizing, - build the CFG and run life analysis. */ - if (!optimize) + build the CFG and run life analysis. + Also need to rebuild life when superblock scheduling is done + as it don't update liveness yet. */ + if (!optimize + || (flag_sched2_use_superblocks + && flag_schedule_insns_after_reload)) { count_or_remove_death_notes (NULL, 1); life_analysis (first, file, PROP_DEATH_NOTES); @@ -448,7 +442,7 @@ reg_to_stack (first, file) FOR_EACH_BB_REVERSE (bb) { edge e; - for (e = bb->pred; e; e=e->pred_next) + for (e = bb->pred; e; e = e->pred_next) if (!(e->flags & EDGE_DFS_BACK) && e->src != ENTRY_BLOCK_PTR) BLOCK_INFO (bb)->predecessors++; @@ -473,7 +467,7 @@ reg_to_stack (first, file) /* A QNaN for initializing uninitialized variables. ??? We can't load from constant memory in PIC mode, because - we're insertting these instructions before the prologue and + we're inserting these instructions before the prologue and the PIC register hasn't been set up. In that case, fall back on zero, which we can get from `ldz'. */ @@ -493,6 +487,7 @@ reg_to_stack (first, file) convert_regs (file); free_aux_for_blocks (); + return true; } /* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the @@ -500,8 +495,7 @@ reg_to_stack (first, file) reference. */ static void -record_label_references (insn, pat) - rtx insn, pat; +record_label_references (rtx insn, rtx pat) { enum rtx_code code = GET_CODE (pat); int i; @@ -554,8 +548,7 @@ record_label_references (insn, pat) PAT that stopped the search. */ static rtx * -get_true_reg (pat) - rtx *pat; +get_true_reg (rtx *pat) { for (;;) switch (GET_CODE (*pat)) @@ -592,8 +585,7 @@ static bool any_malformed_asm; numbers below refer to that explanation. */ static int -check_asm_stack_operands (insn) - rtx insn; +check_asm_stack_operands (rtx insn) { int i; int n_clobbers; @@ -638,7 +630,7 @@ check_asm_stack_operands (insn) if (GET_CODE (body) == PARALLEL) { - clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx)); + clobber_reg = alloca (XVECLEN (body, 0) * sizeof (rtx)); for (i = 0; i < XVECLEN (body, 0); i++) if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) @@ -744,7 +736,7 @@ check_asm_stack_operands (insn) malformed_asm = 1; } - /* Enfore rule #3: If any input operand uses the "f" constraint, all + /* Enforce rule #3: If any input operand uses the "f" constraint, all output constraints must use the "&" earlyclobber. ??? Detect this more deterministically by having constrain_asm_operands @@ -781,8 +773,7 @@ check_asm_stack_operands (insn) placed. */ static int -get_asm_operand_n_inputs (body) - rtx body; +get_asm_operand_n_inputs (rtx body) { if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)); @@ -805,14 +796,13 @@ get_asm_operand_n_inputs (body) return the REG. Otherwise, return 0. */ static rtx -stack_result (decl) - tree decl; +stack_result (tree decl) { rtx result; /* If the value is supposed to be returned in memory, then clearly it is not returned in a stack register. */ - if (aggregate_value_p (DECL_RESULT (decl))) + if (aggregate_value_p (DECL_RESULT (decl), decl)) return 0; result = DECL_RTL_IF_SET (DECL_RESULT (decl)); @@ -839,9 +829,7 @@ stack_result (decl) the desired hard REGNO. */ static void -replace_reg (reg, regno) - rtx *reg; - int regno; +replace_reg (rtx *reg, int regno) { if (regno < FIRST_STACK_REG || regno > LAST_STACK_REG || ! STACK_REG_P (*reg)) @@ -861,10 +849,7 @@ replace_reg (reg, regno) number REGNO from INSN. Remove only one such note. */ static void -remove_regno_note (insn, note, regno) - rtx insn; - enum reg_note note; - unsigned int regno; +remove_regno_note (rtx insn, enum reg_note note, unsigned int regno) { rtx *note_link, this; @@ -887,9 +872,7 @@ remove_regno_note (insn, note, regno) returned if the register is not found. */ static int -get_hard_regnum (regstack, reg) - stack regstack; - rtx reg; +get_hard_regnum (stack regstack, rtx reg) { int i; @@ -911,11 +894,7 @@ get_hard_regnum (regstack, reg) cases the movdf pattern to pop. */ static rtx -emit_pop_insn (insn, regstack, reg, where) - rtx insn; - stack regstack; - rtx reg; - enum emit_where where; +emit_pop_insn (rtx insn, stack regstack, rtx reg, enum emit_where where) { rtx pop_insn, pop_rtx; int hard_regno; @@ -970,10 +949,7 @@ emit_pop_insn (insn, regstack, reg, where) If REG is already at the top of the stack, no insn is emitted. */ static void -emit_swap_insn (insn, regstack, reg) - rtx insn; - stack regstack; - rtx reg; +emit_swap_insn (rtx insn, stack regstack, rtx reg) { int hard_regno; rtx swap_rtx; @@ -997,10 +973,10 @@ emit_swap_insn (insn, regstack, reg) /* Find the previous insn involving stack regs, but don't pass a block boundary. */ i1 = NULL; - if (current_block && insn != current_block->head) + if (current_block && insn != BB_HEAD (current_block)) { rtx tmp = PREV_INSN (insn); - rtx limit = PREV_INSN (current_block->head); + rtx limit = PREV_INSN (BB_HEAD (current_block)); while (tmp != limit) { if (GET_CODE (tmp) == CODE_LABEL @@ -1046,24 +1022,23 @@ emit_swap_insn (insn, regstack, reg) if (i1) emit_insn_after (swap_rtx, i1); else if (current_block) - emit_insn_before (swap_rtx, current_block->head); + emit_insn_before (swap_rtx, BB_HEAD (current_block)); else emit_insn_before (swap_rtx, insn); } /* Handle a move to or from a stack register in PAT, which is in INSN. - REGSTACK is the current stack. */ + REGSTACK is the current stack. Return whether a control flow insn + was deleted in the process. */ -static void -move_for_stack_reg (insn, regstack, pat) - rtx insn; - stack regstack; - rtx pat; +static bool +move_for_stack_reg (rtx insn, stack regstack, rtx pat) { rtx *psrc = get_true_reg (&SET_SRC (pat)); rtx *pdest = get_true_reg (&SET_DEST (pat)); rtx src, dest; rtx note; + bool control_flow_insn_deleted = false; src = *psrc; dest = *pdest; @@ -1093,21 +1068,17 @@ move_for_stack_reg (insn, regstack, pat) If so, just pop the src. */ if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) + emit_pop_insn (insn, regstack, src, EMIT_AFTER); + else { - emit_pop_insn (insn, regstack, src, EMIT_AFTER); - - delete_insn (insn); - return; + regstack->reg[i] = REGNO (dest); + SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); + CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); } - regstack->reg[i] = REGNO (dest); - - SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); - CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); - + control_flow_insn_deleted |= control_flow_insn_p (insn); delete_insn (insn); - - return; + return control_flow_insn_deleted; } /* The source reg does not die. */ @@ -1122,8 +1093,9 @@ move_for_stack_reg (insn, regstack, pat) if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) emit_pop_insn (insn, regstack, dest, EMIT_AFTER); + control_flow_insn_deleted |= control_flow_insn_p (insn); delete_insn (insn); - return; + return control_flow_insn_deleted; } /* The destination ought to be dead. */ @@ -1151,7 +1123,7 @@ move_for_stack_reg (insn, regstack, pat) regstack->top--; CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); } - else if ((GET_MODE (src) == XFmode || GET_MODE (src) == TFmode) + else if ((GET_MODE (src) == XFmode) && regstack->top < REG_STACK_SIZE - 1) { /* A 387 cannot write an XFmode value to a MEM without @@ -1164,10 +1136,7 @@ move_for_stack_reg (insn, regstack, pat) rtx push_rtx, push_insn; rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, GET_MODE (src)); - if (GET_MODE (src) == TFmode) - push_rtx = gen_movtf (top_stack_reg, top_stack_reg); - else - push_rtx = gen_movxf (top_stack_reg, top_stack_reg); + push_rtx = gen_movxf (top_stack_reg, top_stack_reg); push_insn = emit_insn_before (push_rtx, insn); REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg, REG_NOTES (insn)); @@ -1195,6 +1164,8 @@ move_for_stack_reg (insn, regstack, pat) } else abort (); + + return control_flow_insn_deleted; } /* Swap the condition on a branch, if there is one. Return true if we @@ -1202,8 +1173,7 @@ move_for_stack_reg (insn, regstack, pat) such. */ static int -swap_rtx_condition_1 (pat) - rtx pat; +swap_rtx_condition_1 (rtx pat) { const char *fmt; int i, r = 0; @@ -1234,8 +1204,7 @@ swap_rtx_condition_1 (pat) } static int -swap_rtx_condition (insn) - rtx insn; +swap_rtx_condition (rtx insn) { rtx pat = PATTERN (insn); @@ -1263,7 +1232,7 @@ swap_rtx_condition (insn) /* Search forward looking for the first use of this value. Stop at block boundaries. */ - while (insn != current_block->end) + while (insn != BB_END (current_block)) { insn = NEXT_INSN (insn); if (INSN_P (insn) && reg_mentioned_p (dest, insn)) @@ -1322,10 +1291,7 @@ swap_rtx_condition (insn) set up. */ static void -compare_for_stack_reg (insn, regstack, pat_src) - rtx insn; - stack regstack; - rtx pat_src; +compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src) { rtx *src1, *src2; rtx src1_note, src2_note; @@ -1411,15 +1377,14 @@ compare_for_stack_reg (insn, regstack, pat_src) } /* Substitute new registers in PAT, which is part of INSN. REGSTACK - is the current register layout. */ + is the current register layout. Return whether a control flow insn + was deleted in the process. */ -static void -subst_stack_regs_pat (insn, regstack, pat) - rtx insn; - stack regstack; - rtx pat; +static bool +subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) { rtx *dest, *src; + bool control_flow_insn_deleted = false; switch (GET_CODE (pat)) { @@ -1431,7 +1396,7 @@ subst_stack_regs_pat (insn, regstack, pat) && find_regno_note (insn, REG_DEAD, REGNO (*src))) { emit_pop_insn (insn, regstack, *src, EMIT_AFTER); - return; + return control_flow_insn_deleted; } /* ??? Uninitialized USE should not happen. */ else if (get_hard_regnum (regstack, *src) == -1) @@ -1465,7 +1430,7 @@ subst_stack_regs_pat (insn, regstack, pat) abort (); } remove_note (insn, note); - replace_reg (dest, LAST_STACK_REG); + replace_reg (dest, FIRST_STACK_REG + 1); } else { @@ -1481,7 +1446,7 @@ subst_stack_regs_pat (insn, regstack, pat) FP_MODE_REG (REGNO (*dest), SFmode), nan); PATTERN (insn) = pat; - move_for_stack_reg (insn, regstack, 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) @@ -1490,7 +1455,7 @@ subst_stack_regs_pat (insn, regstack, pat) FP_MODE_REG (REGNO (*dest) + 1, SFmode), nan); PATTERN (insn) = pat; - move_for_stack_reg (insn, regstack, pat); + control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat); } } } @@ -1513,7 +1478,7 @@ subst_stack_regs_pat (insn, regstack, pat) && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM || GET_CODE (*src) == CONST_DOUBLE))) { - move_for_stack_reg (insn, regstack, pat); + control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat); break; } @@ -1688,7 +1653,7 @@ subst_stack_regs_pat (insn, regstack, pat) replace_reg (dest, get_hard_regnum (regstack, *dest)); } - /* Keep operand 1 maching with destination. */ + /* Keep operand 1 matching with destination. */ if (GET_RTX_CLASS (GET_CODE (pat_src)) == 'c' && REG_P (*src1) && REG_P (*src2) && REGNO (*src1) != REGNO (*dest)) @@ -1704,6 +1669,8 @@ subst_stack_regs_pat (insn, regstack, pat) { case UNSPEC_SIN: case UNSPEC_COS: + case UNSPEC_FRNDINT: + case UNSPEC_F2XM1: /* These insns only operate on the top of the stack. */ src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); @@ -1725,6 +1692,75 @@ subst_stack_regs_pat (insn, regstack, pat) replace_reg (src1, FIRST_STACK_REG); break; + case UNSPEC_FPATAN: + case UNSPEC_FYL2X: + case UNSPEC_FSCALE: + /* These insns operate on the top two stack slots. */ + + src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); + src2 = get_true_reg (&XVECEXP (pat_src, 0, 1)); + + src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); + src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); + + { + struct stack_def temp_stack; + int regno, j, k, temp; + + temp_stack = *regstack; + + /* Place operand 1 at the top of stack. */ + regno = get_hard_regnum (&temp_stack, *src1); + if (regno < 0) + abort (); + if (regno != FIRST_STACK_REG) + { + k = temp_stack.top - (regno - FIRST_STACK_REG); + j = temp_stack.top; + + temp = temp_stack.reg[k]; + temp_stack.reg[k] = temp_stack.reg[j]; + temp_stack.reg[j] = temp; + } + + /* Place operand 2 next on the stack. */ + regno = get_hard_regnum (&temp_stack, *src2); + if (regno < 0) + abort (); + if (regno != FIRST_STACK_REG + 1) + { + k = temp_stack.top - (regno - FIRST_STACK_REG); + j = temp_stack.top - 1; + + temp = temp_stack.reg[k]; + temp_stack.reg[k] = temp_stack.reg[j]; + temp_stack.reg[j] = temp; + } + + change_stack (insn, regstack, &temp_stack, EMIT_BEFORE); + } + + replace_reg (src1, FIRST_STACK_REG); + replace_reg (src2, FIRST_STACK_REG + 1); + + if (src1_note) + replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); + if (src2_note) + replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1); + + /* Pop both input operands from the stack. */ + CLEAR_HARD_REG_BIT (regstack->reg_set, + regstack->reg[regstack->top]); + CLEAR_HARD_REG_BIT (regstack->reg_set, + regstack->reg[regstack->top - 1]); + regstack->top -= 2; + + /* Push the result back onto the stack. */ + regstack->reg[++regstack->top] = REGNO (*dest); + SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); + replace_reg (dest, FIRST_STACK_REG); + break; + case UNSPEC_SAHF: /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF) The combination matches the PPRO fcomi instruction. */ @@ -1733,7 +1769,7 @@ subst_stack_regs_pat (insn, regstack, pat) if (GET_CODE (pat_src) != UNSPEC || XINT (pat_src, 1) != UNSPEC_FNSTSW) abort (); - /* FALLTHRU */ + /* Fall through. */ case UNSPEC_FNSTSW: /* Combined fcomp+fnstsw generated for doing well with @@ -1846,6 +1882,8 @@ subst_stack_regs_pat (insn, regstack, pat) default: break; } + + return control_flow_insn_deleted; } /* Substitute hard regnums for any stack regs in INSN, which has @@ -1859,9 +1897,7 @@ subst_stack_regs_pat (insn, regstack, pat) requirements, since record_asm_stack_regs removes any problem asm. */ static void -subst_asm_stack_regs (insn, regstack) - rtx insn; - stack regstack; +subst_asm_stack_regs (rtx insn, stack regstack) { rtx body = PATTERN (insn); int alt; @@ -1912,9 +1948,9 @@ subst_asm_stack_regs (insn, regstack) for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1)) i++; - note_reg = (rtx *) alloca (i * sizeof (rtx)); - note_loc = (rtx **) alloca (i * sizeof (rtx *)); - note_kind = (enum reg_note *) alloca (i * sizeof (enum reg_note)); + note_reg = alloca (i * sizeof (rtx)); + note_loc = alloca (i * sizeof (rtx *)); + note_kind = alloca (i * sizeof (enum reg_note)); n_notes = 0; for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) @@ -1945,8 +1981,8 @@ subst_asm_stack_regs (insn, regstack) if (GET_CODE (body) == PARALLEL) { - clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx)); - clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx *)); + clobber_reg = alloca (XVECLEN (body, 0) * sizeof (rtx)); + clobber_loc = alloca (XVECLEN (body, 0) * sizeof (rtx *)); for (i = 0; i < XVECLEN (body, 0); i++) if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) @@ -2145,14 +2181,14 @@ subst_asm_stack_regs (insn, regstack) /* Substitute stack hard reg numbers for stack virtual registers in INSN. Non-stack register numbers are not changed. REGSTACK is the current stack content. Insns may be emitted as needed to arrange the - stack for the 387 based on the contents of the insn. */ + stack for the 387 based on the contents of the insn. Return whether + a control flow insn was deleted in the process. */ -static void -subst_stack_regs (insn, regstack) - rtx insn; - stack regstack; +static bool +subst_stack_regs (rtx insn, stack regstack) { rtx *note_link, note; + bool control_flow_insn_deleted = false; int i; if (GET_CODE (insn) == CALL_INSN) @@ -2193,25 +2229,27 @@ subst_stack_regs (insn, regstack) Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */ subst_asm_stack_regs (insn, regstack); - return; + return control_flow_insn_deleted; } if (GET_CODE (PATTERN (insn)) == PARALLEL) for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) { if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i))) - subst_stack_regs_pat (insn, regstack, - XVECEXP (PATTERN (insn), 0, i)); + control_flow_insn_deleted + |= subst_stack_regs_pat (insn, regstack, + XVECEXP (PATTERN (insn), 0, i)); } else - subst_stack_regs_pat (insn, regstack, PATTERN (insn)); + control_flow_insn_deleted + |= subst_stack_regs_pat (insn, regstack, PATTERN (insn)); } /* subst_stack_regs_pat may have deleted a no-op insn. If so, any REG_UNUSED will already have been dealt with, so just return. */ if (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn)) - return; + return control_flow_insn_deleted; /* If there is a REG_UNUSED note on a stack register on this insn, the indicated reg must be popped. The REG_UNUSED note is removed, @@ -2227,6 +2265,8 @@ subst_stack_regs (insn, regstack) } else note_link = &XEXP (note, 1); + + return control_flow_insn_deleted; } /* Change the organization of the stack so that it fits a new basic @@ -2242,11 +2282,7 @@ subst_stack_regs (insn, regstack) is no longer needed once this has executed. */ static void -change_stack (insn, old, new, where) - rtx insn; - stack old; - stack new; - enum emit_where where; +change_stack (rtx insn, stack old, stack new, enum emit_where where) { int reg; int update_end = 0; @@ -2256,7 +2292,7 @@ change_stack (insn, old, new, where) if (where == EMIT_AFTER) { - if (current_block && current_block->end == insn) + if (current_block && BB_END (current_block) == insn) update_end = 1; insn = NEXT_INSN (insn); } @@ -2339,15 +2375,13 @@ change_stack (insn, old, new, where) } if (update_end) - current_block->end = PREV_INSN (insn); + BB_END (current_block) = PREV_INSN (insn); } /* Print stack configuration. */ static void -print_stack (file, s) - FILE *file; - stack s; +print_stack (FILE *file, stack s) { if (! file) return; @@ -2375,7 +2409,7 @@ print_stack (file, s) commit_edge_insertions needs to be called. */ static int -convert_regs_entry () +convert_regs_entry (void) { int inserted = 0; edge e; @@ -2405,7 +2439,7 @@ convert_regs_entry () the push/pop code happy, and to not scrog the register stack, we must put something in these registers. Use a QNaN. - Note that we are insertting converted code here. This code is + Note that we are inserting converted code here. This code is never seen by the convert_regs pass. */ for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next) @@ -2438,7 +2472,7 @@ convert_regs_entry () be `empty', or the function return value at top-of-stack. */ static void -convert_regs_exit () +convert_regs_exit (void) { int value_reg_low, value_reg_high; stack output_stack; @@ -2473,9 +2507,7 @@ convert_regs_exit () target block, or copy stack info into the stack of the successor of the successor hasn't been processed yet. */ static bool -compensate_edge (e, file) - edge e; - FILE *file; +compensate_edge (edge e, FILE *file) { basic_block block = e->src, target = e->dest; block_info bi = BLOCK_INFO (block); @@ -2504,7 +2536,7 @@ compensate_edge (e, file) /* change_stack kills values in regstack. */ tmpstack = regstack; - change_stack (block->end, &tmpstack, target_stack, EMIT_AFTER); + change_stack (BB_END (block), &tmpstack, target_stack, EMIT_AFTER); return false; } @@ -2575,8 +2607,8 @@ compensate_edge (e, file) /* change_stack kills values in regstack. */ tmpstack = regstack; - change_stack (block->end, &tmpstack, target_stack, - (GET_CODE (block->end) == JUMP_INSN + change_stack (BB_END (block), &tmpstack, target_stack, + (GET_CODE (BB_END (block)) == JUMP_INSN ? EMIT_BEFORE : EMIT_AFTER)); } else @@ -2593,7 +2625,7 @@ compensate_edge (e, file) start_sequence (); /* ??? change_stack needs some point to emit insns after. */ - after = emit_note (NULL, NOTE_INSN_DELETED); + after = emit_note (NOTE_INSN_DELETED); tmpstack = regstack; change_stack (after, &tmpstack, target_stack, EMIT_BEFORE); @@ -2610,15 +2642,14 @@ compensate_edge (e, file) /* Convert stack register references in one block. */ static int -convert_regs_1 (file, block) - FILE *file; - basic_block block; +convert_regs_1 (FILE *file, basic_block block) { struct stack_def regstack; block_info bi = BLOCK_INFO (block); int deleted, inserted, reg; rtx insn, next; edge e, beste = NULL; + bool control_flow_insn_deleted = false; inserted = 0; deleted = 0; @@ -2683,7 +2714,7 @@ convert_regs_1 (file, block) /* Process all insns in this block. Keep track of NEXT so that we don't process insns emitted while substituting in INSN. */ - next = block->head; + next = BB_HEAD (block); regstack = bi->stack_in; do { @@ -2693,7 +2724,7 @@ convert_regs_1 (file, block) /* Ensure we have not missed a block boundary. */ if (next == NULL) abort (); - if (insn == block->end) + if (insn == BB_END (block)) next = NULL; /* Don't bother processing unless there is a stack reg @@ -2707,8 +2738,7 @@ convert_regs_1 (file, block) INSN_UID (insn)); print_stack (file, ®stack); } - subst_stack_regs (insn, ®stack); - deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn)); + control_flow_insn_deleted |= subst_stack_regs (insn, ®stack); } } while (next); @@ -2723,7 +2753,7 @@ convert_regs_1 (file, block) print_stack (file, ®stack); } - insn = block->end; + insn = BB_END (block); if (GET_CODE (insn) == JUMP_INSN) insn = PREV_INSN (insn); @@ -2747,8 +2777,7 @@ convert_regs_1 (file, block) set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode), nan); insn = emit_insn_after (set, insn); - subst_stack_regs (insn, ®stack); - deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn)); + control_flow_insn_deleted |= subst_stack_regs (insn, ®stack); } } @@ -2758,12 +2787,18 @@ convert_regs_1 (file, block) called at the end of convert_regs. The order in which we process the blocks ensures that we never delete an already processed edge. + Note that, at this point, the CFG may have been damaged by the emission + of instructions after an abnormal call, which moves the basic block end + (and is the reason why we call fixup_abnormal_edges later). So we must + be sure that the trapping insn has been deleted before trying to purge + dead edges, otherwise we risk purging valid edges. + ??? We are normally supposed not to delete trapping insns, so we pretend that the insns deleted above don't actually trap. It would have been better to detect this earlier and avoid creating the EH edge in the first place, still, but we don't have enough information at that time. */ - if (deleted) + if (control_flow_insn_deleted) purge_dead_edges (block); /* Something failed if the stack lives don't match. If we had malformed @@ -2804,9 +2839,7 @@ convert_regs_1 (file, block) /* Convert registers in all blocks reachable from BLOCK. */ static int -convert_regs_2 (file, block) - FILE *file; - basic_block block; +convert_regs_2 (FILE *file, basic_block block) { basic_block *stack, *sp; int inserted; @@ -2815,7 +2848,7 @@ convert_regs_2 (file, block) is only processed after all its predecessors. The number of predecessors of every block has already been computed. */ - stack = (basic_block *) xmalloc (sizeof (*stack) * n_basic_blocks); + stack = xmalloc (sizeof (*stack) * n_basic_blocks); sp = stack; *sp++ = block; @@ -2861,8 +2894,7 @@ convert_regs_2 (file, block) to the stack-like registers the 387 uses. */ static int -convert_regs (file) - FILE *file; +convert_regs (FILE *file) { int inserted; basic_block b; |