/* Mark pseudo REGNO as living at program point POINT, update conflicting hard registers of the pseudo and START_LIVING, and start a new live range for the pseudo corresponding to REGNO if it is necessary. */ static void mark_pseudo_live (int regno, int point) { lra_live_range_t p; lra_assert (regno >= FIRST_PSEUDO_REGISTER); lra_assert (! sparseset_bit_p (pseudos_live, regno)); sparseset_set_bit (pseudos_live, regno); IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, hard_regs_live); if ((complete_info_p || lra_get_regno_hard_regno (regno) < 0) && ((p = lra_reg_info[regno].live_ranges) == NULL || (p->finish != point && p->finish + 1 != point))) lra_reg_info[regno].live_ranges = create_live_range (regno, point, -1, p); sparseset_set_bit (start_living, regno); }
/* Spill pseudos which are assigned to hard registers in SET. Add affected insns for processing in the subsequent constraint pass. */ static void spill_pseudos (HARD_REG_SET set) { int i; bitmap_head to_process; rtx_insn *insn; if (hard_reg_set_empty_p (set)) return; if (lra_dump_file != NULL) { fprintf (lra_dump_file, " Spilling non-eliminable hard regs:"); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (set, i)) fprintf (lra_dump_file, " %d", i); fprintf (lra_dump_file, "\n"); } bitmap_initialize (&to_process, ®_obstack); for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++) if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0 && overlaps_hard_reg_set_p (set, PSEUDO_REGNO_MODE (i), reg_renumber[i])) { if (lra_dump_file != NULL) fprintf (lra_dump_file, " Spilling r%d(%d)\n", i, reg_renumber[i]); reg_renumber[i] = -1; bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap); } IOR_HARD_REG_SET (lra_no_alloc_regs, set); for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) if (bitmap_bit_p (&to_process, INSN_UID (insn))) { lra_push_insn (insn); lra_set_used_insn_alternative (insn, -1); } bitmap_clear (&to_process); }
/* Update all offsets and possibility for elimination on eliminable registers. Spill pseudos assigned to registers which are uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET. Add insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard registers whose offsets should be changed. Return true if any elimination offset changed. */ static bool update_reg_eliminate (bitmap insns_with_changed_offsets) { bool prev, result; struct lra_elim_table *ep, *ep1; HARD_REG_SET temp_hard_reg_set; /* Clear self elimination offsets. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) self_elim_offsets[ep->from] = 0; for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { /* If it is a currently used elimination: update the previous offset. */ if (elimination_map[ep->from] == ep) ep->previous_offset = ep->offset; prev = ep->prev_can_eliminate; setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to)); if (ep->can_eliminate && ! prev) { /* It is possible that not eliminable register becomes eliminable because we took other reasons into account to set up eliminable regs in the initial set up. Just ignore new eliminable registers. */ setup_can_eliminate (ep, false); continue; } if (ep->can_eliminate != prev && elimination_map[ep->from] == ep) { /* We cannot use this elimination anymore -- find another one. */ if (lra_dump_file != NULL) fprintf (lra_dump_file, " Elimination %d to %d is not possible anymore\n", ep->from, ep->to); /* If after processing RTL we decides that SP can be used as a result of elimination, it can not be changed. */ gcc_assert ((ep->to_rtx != stack_pointer_rtx) || (ep->from < FIRST_PSEUDO_REGISTER && fixed_regs [ep->from])); /* Mark that is not eliminable anymore. */ elimination_map[ep->from] = NULL; for (ep1 = ep + 1; ep1 < ®_eliminate[NUM_ELIMINABLE_REGS]; ep1++) if (ep1->can_eliminate && ep1->from == ep->from) break; if (ep1 < ®_eliminate[NUM_ELIMINABLE_REGS]) { if (lra_dump_file != NULL) fprintf (lra_dump_file, " Using elimination %d to %d now\n", ep1->from, ep1->to); lra_assert (ep1->previous_offset == 0); ep1->previous_offset = ep->offset; } else { /* There is no elimination anymore just use the hard register `from' itself. Setup self elimination offset to restore the original offset values. */ if (lra_dump_file != NULL) fprintf (lra_dump_file, " %d is not eliminable at all\n", ep->from); self_elim_offsets[ep->from] = -ep->offset; if (ep->offset != 0) bitmap_ior_into (insns_with_changed_offsets, &lra_reg_info[ep->from].insn_bitmap); } } INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->offset); } setup_elimination_map (); result = false; CLEAR_HARD_REG_SET (temp_hard_reg_set); for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) if (elimination_map[ep->from] == NULL) SET_HARD_REG_BIT (temp_hard_reg_set, ep->from); else if (elimination_map[ep->from] == ep) { /* Prevent the hard register into which we eliminate from the usage for pseudos. */ if (ep->from != ep->to) SET_HARD_REG_BIT (temp_hard_reg_set, ep->to); if (ep->previous_offset != ep->offset) { bitmap_ior_into (insns_with_changed_offsets, &lra_reg_info[ep->from].insn_bitmap); /* Update offset when the eliminate offset have been changed. */ lra_update_reg_val_offset (lra_reg_info[ep->from].val, ep->offset - ep->previous_offset); result = true; } } IOR_HARD_REG_SET (lra_no_alloc_regs, temp_hard_reg_set); AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set); spill_pseudos (temp_hard_reg_set); return result; }