static void clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length) { basic_block bb; regset_head live; HARD_REG_SET hlive; rtx x; int i; /* Initialize liveness propagation. */ bb = BLOCK_FOR_INSN (insn); INIT_REG_SET (&live); bitmap_copy (&live, DF_LR_OUT (bb)); df_simulate_initialize_backwards (bb, &live); /* Propagate until INSN if found. */ for (x = BB_END (bb); x != insn; x = PREV_INSN (x)) df_simulate_one_insn_backwards (bb, x, &live); /* Clear registers live after INSN. */ renumbered_reg_set_to_hard_reg_set (&hlive, &live); AND_COMPL_HARD_REG_SET (*regs, hlive); /* Clear registers live in and before the sequence. */ for (i = 0; i < length;) { rtx prev = PREV_INSN (x); df_simulate_one_insn_backwards (bb, x, &live); if (INSN_P (x)) { renumbered_reg_set_to_hard_reg_set (&hlive, &live); AND_COMPL_HARD_REG_SET (*regs, hlive); i++; } x = prev; } /* Free unused data. */ CLEAR_REG_SET (&live); }
/* 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; }