/* 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); }
/* If INSN can not be used for rematerialization, return negative value. If INSN can be considered as a candidate for rematerialization, return value which is the operand number of the pseudo for which the insn can be used for rematerialization. Here we consider the insns without any memory, spilled pseudo (except for the rematerialization pseudo), or dying or unused regs. */ static int operand_to_remat (rtx_insn *insn) { lra_insn_recog_data_t id = lra_get_insn_recog_data (insn); struct lra_static_insn_data *static_id = id->insn_static_data; struct lra_insn_reg *reg, *found_reg = NULL; /* Don't rematerialize insns which can change PC. */ if (JUMP_P (insn) || CALL_P (insn)) return -1; /* First find a pseudo which can be rematerialized. */ for (reg = id->regs; reg != NULL; reg = reg->next) /* True FRAME_POINTER_NEEDED might be because we can not follow changing sp offsets, e.g. alloca is used. If the insn contains stack pointer in such case, we can not rematerialize it as we can not know sp offset at a rematerialization place. */ if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed) return -1; else if (reg->type == OP_OUT && ! reg->subreg_p && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL) { /* We permits only one spilled reg. */ if (found_reg != NULL) return -1; found_reg = reg; } /* IRA calculates conflicts separately for subregs of two words pseudo. Even if the pseudo lives, e.g. one its subreg can be used lately, another subreg hard register can be already used for something else. In such case, it is not safe to rematerialize the insn. */ else if (reg->type == OP_IN && reg->subreg_p && reg->regno >= FIRST_PSEUDO_REGISTER && (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)) == 2 * UNITS_PER_WORD)) return -1; if (found_reg == NULL) return -1; if (found_reg->regno < FIRST_PSEUDO_REGISTER) return -1; if (bad_for_rematerialization_p (PATTERN (insn))) return -1; /* Check the other regs are not spilled. */ for (reg = id->regs; reg != NULL; reg = reg->next) if (found_reg == reg) continue; else if (reg->type == OP_INOUT) return -1; else if (reg->regno >= FIRST_PSEUDO_REGISTER && reg_renumber[reg->regno] < 0) /* Another spilled reg. */ return -1; else if (reg->type == OP_IN) { if (find_regno_note (insn, REG_DEAD, reg->regno) != NULL) /* We don't want to make live ranges longer. */ return -1; /* Check that there is no output reg as the input one. */ for (struct lra_insn_reg *reg2 = id->regs; reg2 != NULL; reg2 = reg2->next) if (reg2->type == OP_OUT && reg->regno == reg2->regno) return -1; if (reg->regno < FIRST_PSEUDO_REGISTER) for (struct lra_insn_reg *reg2 = static_id->hard_regs; reg2 != NULL; reg2 = reg2->next) if (reg2->type == OP_OUT && reg->regno <= reg2->regno && (reg2->regno < (reg->regno + hard_regno_nregs[reg->regno][reg->biggest_mode]))) return -1; } /* Find the rematerialization operand. */ int nop = static_id->n_operands; for (int i = 0; i < nop; i++) if (REG_P (*id->operand_loc[i]) && (int) REGNO (*id->operand_loc[i]) == found_reg->regno) return i; return -1; }