diff options
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r-- | gcc/reg-stack.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 2f94958a2e2..ff09ad224d9 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -1327,6 +1327,30 @@ compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src) } } +/* Substitute new registers in LOC, which is part of a debug insn. + REGSTACK is the current register layout. */ + +static int +subst_stack_regs_in_debug_insn (rtx *loc, void *data) +{ + rtx *tloc = get_true_reg (loc); + stack regstack = (stack)data; + int hard_regno; + + if (!STACK_REG_P (*tloc)) + return 0; + + if (tloc != loc) + return 0; + + hard_regno = get_hard_regnum (regstack, *loc); + gcc_assert (hard_regno >= FIRST_STACK_REG); + + replace_reg (loc, hard_regno); + + return -1; +} + /* Substitute new registers in PAT, which is part of INSN. REGSTACK is the current register layout. Return whether a control flow insn was deleted in the process. */ @@ -1360,6 +1384,9 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) since the REG_DEAD notes are not issued.) */ break; + case VAR_LOCATION: + gcc_unreachable (); + case CLOBBER: { rtx note; @@ -2871,6 +2898,7 @@ convert_regs_1 (basic_block block) int reg; rtx insn, next; bool control_flow_insn_deleted = false; + int debug_insns_with_starting_stack = 0; any_malformed_asm = false; @@ -2923,8 +2951,25 @@ convert_regs_1 (basic_block block) /* Don't bother processing unless there is a stack reg mentioned or if it's a CALL_INSN. */ - if (stack_regs_mentioned (insn) - || CALL_P (insn)) + if (DEBUG_INSN_P (insn)) + { + if (starting_stack_p) + debug_insns_with_starting_stack++; + else + { + for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn, + ®stack); + + /* Nothing must ever die at a debug insn. If something + is referenced in it that becomes dead, it should have + died before and the reference in the debug insn + should have been removed so as to avoid changing code + generation. */ + gcc_assert (!find_reg_note (insn, REG_DEAD, NULL)); + } + } + else if (stack_regs_mentioned (insn) + || CALL_P (insn)) { if (dump_file) { @@ -2938,6 +2983,24 @@ convert_regs_1 (basic_block block) } while (next); + if (debug_insns_with_starting_stack) + { + /* Since it's the first non-debug instruction that determines + the stack requirements of the current basic block, we refrain + from updating debug insns before it in the loop above, and + fix them up here. */ + for (insn = BB_HEAD (block); debug_insns_with_starting_stack; + insn = NEXT_INSN (insn)) + { + if (!DEBUG_INSN_P (insn)) + continue; + + debug_insns_with_starting_stack--; + for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn, + &bi->stack_in); + } + } + if (dump_file) { fprintf (dump_file, "Expected live registers ["); |