diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e26be78c65c..3a7c61ebae2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2000-05-11 Stan Cox + + * regrename.c (replace_reg_in_block): Improve REG_DEAD handling. + * timevar.def (TV_RENAME_REGISTERS): Move before TV_SCHED2. + * toplev.c (rest_of_compilation): Call regrename_optimize before sched2. + 2000-05-11 Bruce Korb * fixinc/fixfixes.c(double_slash_fix): obsolete diff --git a/gcc/regrename.c b/gcc/regrename.c index 26129496f14..d5e8160c94f 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -526,8 +526,11 @@ replace_reg_in_block (du, uid_ruid, def, reg_def, avail_reg) unsigned int avail_reg; { int du_idx, status = 1; + int last_replaced_insn; unsigned int r = REGNO (reg_def); rtx death_note; + rtx reg_notes; + rtx reg_use; rtx new_reg = gen_rtx_REG (GET_MODE (reg_def), avail_reg); rr_replace_reg (PATTERN (VARRAY_RTX (*uid_ruid, def)), reg_def, new_reg, @@ -536,39 +539,64 @@ replace_reg_in_block (du, uid_ruid, def, reg_def, avail_reg) if (!status) return status; - death_note = find_reg_note (VARRAY_RTX (*uid_ruid, def), REG_DEAD, reg_def); - if (!death_note) - death_note = find_reg_note (VARRAY_RTX (*uid_ruid, def), REG_UNUSED, - reg_def); + death_note = 0; + /* This typically happens if a constraint check failed and the register + changes are being reversed. */ + for (reg_notes = REG_NOTES (VARRAY_RTX (*uid_ruid, def)); + reg_notes; reg_notes = XEXP (reg_notes, 1)) + { + if (REG_NOTE_KIND (reg_notes) == REG_DEAD + && REGNO (XEXP (reg_notes, 0)) == avail_reg) + death_note = reg_notes; + } if (death_note) - rr_replace_reg (death_note, reg_def, new_reg, 0, - VARRAY_RTX (*uid_ruid, def), &status); + remove_note (VARRAY_RTX (*uid_ruid, def), death_note); + + /* The old destination is now dead if it is also a source. */ + if (regno_use_in (r, PATTERN (VARRAY_RTX (*uid_ruid, def)))) + REG_NOTES (VARRAY_RTX (*uid_ruid, def)) + = gen_rtx_EXPR_LIST (REG_DEAD, reg_def, + REG_NOTES (VARRAY_RTX (*uid_ruid, + def))); + last_replaced_insn = 0; + + /* Now replace in the uses. */ for (du_idx = def + 1; du_idx < du->high_bound; du_idx++) { - rtx reg_use; - rtx new_reg; - if (GET_RTX_CLASS (GET_CODE (VARRAY_RTX (*uid_ruid, du_idx))) != 'i') continue; reg_use = regno_use_in (r, PATTERN (VARRAY_RTX (*uid_ruid, du_idx))); + if (reg_use && TEST_BIT (du->uses[r], du_idx)) { new_reg = gen_rtx_REG (GET_MODE (reg_use), avail_reg); + rr_replace_reg (PATTERN (VARRAY_RTX (*uid_ruid, du_idx)), reg_use, new_reg, SOURCE, VARRAY_RTX (*uid_ruid, du_idx), &status); death_note = find_reg_note (VARRAY_RTX (*uid_ruid, du_idx), REG_DEAD, reg_use); - if (!death_note) - death_note = find_reg_note (VARRAY_RTX (*uid_ruid, du_idx), - REG_UNUSED, reg_use); if (death_note) - rr_replace_reg (death_note, reg_use, new_reg, 0, - VARRAY_RTX (*uid_ruid, def), &status); + { + REG_NOTES (VARRAY_RTX (*uid_ruid, du_idx)) + = gen_rtx_EXPR_LIST (REG_DEAD, new_reg, + REG_NOTES (VARRAY_RTX (*uid_ruid, + du_idx))); + remove_note (VARRAY_RTX (*uid_ruid, du_idx), + find_reg_note (VARRAY_RTX (*uid_ruid, du_idx), + REG_DEAD, reg_use)); + } + } + /* This insn may contain shared rtl replaced in the previous iteration. + Treat this equivalent to the rr_replace_reg case. */ + if (TEST_BIT (du->uses[r], du_idx)) + { + last_replaced_insn = du_idx; + SET_BIT (du->uses[avail_reg], du_idx); RESET_BIT (du->uses[r], du_idx); if (!status) @@ -579,6 +607,27 @@ replace_reg_in_block (du, uid_ruid, def, reg_def, avail_reg) break; } + /* Add REG_DEAD note for replaced register at last use. */ + + if (last_replaced_insn) + { + new_reg = regno_use_in (avail_reg, + PATTERN (VARRAY_RTX (*uid_ruid, + last_replaced_insn))); + if (new_reg + && ! find_reg_note (VARRAY_RTX (*uid_ruid, last_replaced_insn), + REG_DEAD, new_reg)) + { + REG_NOTES (VARRAY_RTX (*uid_ruid, last_replaced_insn)) + = gen_rtx_EXPR_LIST (REG_DEAD, new_reg, + REG_NOTES (VARRAY_RTX (*uid_ruid, + last_replaced_insn))); + remove_note (VARRAY_RTX (*uid_ruid, last_replaced_insn), + find_reg_note (VARRAY_RTX (*uid_ruid, last_replaced_insn), + REG_DEAD, reg_use)); + } + } + return status; } @@ -611,7 +660,7 @@ rr_replace_reg (x, reg_use, reg_sub, replace_type, insn, status) if (GET_MODE (x) == GET_MODE (reg_use)) return reg_sub; else - return gen_rtx_REG (GET_MODE (x), REGNO (reg_use)); + return gen_rtx_REG (GET_MODE (x), REGNO (reg_sub)); } return x; diff --git a/gcc/timevar.def b/gcc/timevar.def index 401719a9e92..fcf21772c02 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -60,10 +60,10 @@ DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs") DEFTIMEVAR (TV_FLOW2 , "flow 2") DEFTIMEVAR (TV_IFCVT2 , "if-conversion 2") DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2") -DEFTIMEVAR (TV_SCHED2 , "schedulding 2") +DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers") +DEFTIMEVAR (TV_SCHED2 , "scheduling 2") DEFTIMEVAR (TV_DBR_SCHED , "delay branch sched") DEFTIMEVAR (TV_REORDER_BLOCKS , "reorder blocks") -DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers") DEFTIMEVAR (TV_SHORTEN_BRANCH , "shorten branches") DEFTIMEVAR (TV_REG_STACK , "reg stack") DEFTIMEVAR (TV_TO_SSA , "convert to SSA") diff --git a/gcc/toplev.c b/gcc/toplev.c index 05d18469893..1d89a7c686b 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -272,9 +272,9 @@ enum dump_file_index DFI_flow2, DFI_ce2, DFI_peephole2, + DFI_rnreg, DFI_sched2, DFI_bbro, - DFI_rnreg, DFI_jump2, DFI_mach, DFI_dbr, @@ -314,9 +314,9 @@ struct dump_file_info dump_file[DFI_MAX] = { "flow2", 'w', 1, 0, 0 }, { "ce2", 'E', 1, 0, 0 }, { "peephole2", 'z', 1, 0, 0 }, + { "rnreg", 'n', 1, 0, 0 }, { "sched2", 'R', 1, 0, 0 }, { "bbro", 'B', 1, 0, 0 }, - { "rnreg", 'n', 1, 0, 0 }, { "jump2", 'J', 1, 0, 0 }, { "mach", 'M', 1, 0, 0 }, { "dbr", 'd', 0, 0, 0 }, @@ -3358,7 +3358,7 @@ rest_of_compilation (decl) cleanup_cfg (insns); life_analysis (insns, rtl_dump_file, PROP_FINAL); - /* This is kind of heruistics. We need to run combine_stack_adjustments + /* This is kind of a heuristic. We need to run combine_stack_adjustments even for machines with possibly nonzero RETURN_POPS_ARGS and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having push instructions will have popping returns. */ @@ -3400,6 +3400,17 @@ rest_of_compilation (decl) } #endif + if (optimize > 0 && flag_rename_registers) + { + timevar_push (TV_RENAME_REGISTERS); + open_dump_file (DFI_rnreg, decl); + + regrename_optimize (); + + close_dump_file (DFI_rnreg, print_rtl_with_bb, insns); + timevar_pop (TV_RENAME_REGISTERS); + } + #ifdef INSN_SCHEDULING if (optimize > 0 && flag_schedule_insns_after_reload) { @@ -3435,17 +3446,6 @@ rest_of_compilation (decl) timevar_pop (TV_REORDER_BLOCKS); } - if (optimize > 0 && flag_rename_registers) - { - timevar_push (TV_RENAME_REGISTERS); - open_dump_file (DFI_rnreg, decl); - - regrename_optimize (); - - close_dump_file (DFI_rnreg, print_rtl_with_bb, insns); - timevar_pop (TV_RENAME_REGISTERS); - } - /* One more attempt to remove jumps to .+1 left by dead-store elimination. Also do cross-jumping this time and delete no-op move insns. */