📄 local-alloc.c
字号:
{ /* Note that the quotient will never be bigger than the value of floor_log2 times the maximum number of times a register can occur in one insn (surely less than 100). Multiplying this by 10000 can't overflow. */ register int pri1 = (((double) (floor_log2 (qty_n_refs[q1]) * qty_n_refs[q1] * qty_size[q1]) / (qty_death[q1] - qty_birth[q1])) * 10000); register int pri2 = (((double) (floor_log2 (qty_n_refs[q2]) * qty_n_refs[q2] * qty_size[q2]) / (qty_death[q2] - qty_birth[q2])) * 10000); return pri2 - pri1;}static intqty_compare_1 (q1, q2) int *q1, *q2;{ register int tem; /* Note that the quotient will never be bigger than the value of floor_log2 times the maximum number of times a register can occur in one insn (surely less than 100). Multiplying this by 10000 can't overflow. */ register int pri1 = (((double) (floor_log2 (qty_n_refs[*q1]) * qty_n_refs[*q1] * qty_size[*q1]) / (qty_death[*q1] - qty_birth[*q1])) * 10000); register int pri2 = (((double) (floor_log2 (qty_n_refs[*q2]) * qty_n_refs[*q2] * qty_size[*q2]) / (qty_death[*q2] - qty_birth[*q2])) * 10000); tem = pri2 - pri1; if (tem != 0) return tem; /* If qtys are equally good, sort by qty number, so that the results of qsort leave nothing to chance. */ return *q1 - *q2;}/* Compare two quantities' priority for getting real registers. This version is called for quantities that have suggested hard registers. First priority goes to quantities that have copy preferences, then to those that have normal preferences. Within those groups, quantities with the lower number of preferences have the highest priority. Of those, we use the same algorithm as above. */static intqty_sugg_compare (q1, q2) int q1, q2;{ register int sugg1 = (qty_phys_num_copy_sugg[q1] ? qty_phys_num_copy_sugg[q1] : qty_phys_num_sugg[q1] * FIRST_PSEUDO_REGISTER); register int sugg2 = (qty_phys_num_copy_sugg[q2] ? qty_phys_num_copy_sugg[q2] : qty_phys_num_sugg[q2] * FIRST_PSEUDO_REGISTER); /* Note that the quotient will never be bigger than the value of floor_log2 times the maximum number of times a register can occur in one insn (surely less than 100). Multiplying this by 10000 can't overflow. */ register int pri1 = (((double) (floor_log2 (qty_n_refs[q1]) * qty_n_refs[q1] * qty_size[q1]) / (qty_death[q1] - qty_birth[q1])) * 10000); register int pri2 = (((double) (floor_log2 (qty_n_refs[q2]) * qty_n_refs[q2] * qty_size[q2]) / (qty_death[q2] - qty_birth[q2])) * 10000); if (sugg1 != sugg2) return sugg1 - sugg2; return pri2 - pri1;}static intqty_sugg_compare_1 (q1, q2) int *q1, *q2;{ register int sugg1 = (qty_phys_num_copy_sugg[*q1] ? qty_phys_num_copy_sugg[*q1] : qty_phys_num_sugg[*q1] * FIRST_PSEUDO_REGISTER); register int sugg2 = (qty_phys_num_copy_sugg[*q2] ? qty_phys_num_copy_sugg[*q2] : qty_phys_num_sugg[*q2] * FIRST_PSEUDO_REGISTER); /* Note that the quotient will never be bigger than the value of floor_log2 times the maximum number of times a register can occur in one insn (surely less than 100). Multiplying this by 10000 can't overflow. */ register int pri1 = (((double) (floor_log2 (qty_n_refs[*q1]) * qty_n_refs[*q1] * qty_size[*q1]) / (qty_death[*q1] - qty_birth[*q1])) * 10000); register int pri2 = (((double) (floor_log2 (qty_n_refs[*q2]) * qty_n_refs[*q2] * qty_size[*q2]) / (qty_death[*q2] - qty_birth[*q2])) * 10000); if (sugg1 != sugg2) return sugg1 - sugg2; if (pri1 != pri2) return pri2 - pri1; /* If qtys are equally good, sort by qty number, so that the results of qsort leave nothing to chance. */ return *q1 - *q2;}/* Attempt to combine the two registers (rtx's) USEDREG and SETREG. Returns 1 if have done so, or 0 if cannot. Combining registers means marking them as having the same quantity and adjusting the offsets within the quantity if either of them is a SUBREG). We don't actually combine a hard reg with a pseudo; instead we just record the hard reg as the suggestion for the pseudo's quantity. If we really combined them, we could lose if the pseudo lives across an insn that clobbers the hard reg (eg, movstr). ALREADY_DEAD is non-zero if USEDREG is known to be dead even though there is no REG_DEAD note on INSN. This occurs during the processing of REG_NO_CONFLICT blocks. MAY_SAVE_COPYCOPY is non-zero if this insn is simply copying USEDREG to SETREG or if the input and output must share a register. In that case, we record a hard reg suggestion in QTY_PHYS_COPY_SUGG. There are elaborate checks for the validity of combining. */ static intcombine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead) rtx usedreg, setreg; int may_save_copy; int insn_number; rtx insn; int already_dead;{ register int ureg, sreg; register int offset = 0; int usize, ssize; register int sqty; /* Determine the numbers and sizes of registers being used. If a subreg is present that does not change the entire register, don't consider this a copy insn. */ while (GET_CODE (usedreg) == SUBREG) { if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD) may_save_copy = 0; offset += SUBREG_WORD (usedreg); usedreg = SUBREG_REG (usedreg); } if (GET_CODE (usedreg) != REG) return 0; ureg = REGNO (usedreg); usize = REG_SIZE (usedreg); while (GET_CODE (setreg) == SUBREG) { if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (setreg))) > UNITS_PER_WORD) may_save_copy = 0; offset -= SUBREG_WORD (setreg); setreg = SUBREG_REG (setreg); } if (GET_CODE (setreg) != REG) return 0; sreg = REGNO (setreg); ssize = REG_SIZE (setreg); /* If UREG is a pseudo-register that hasn't already been assigned a quantity number, it means that it is not local to this block or dies more than once. In either event, we can't do anything with it. */ if ((ureg >= FIRST_PSEUDO_REGISTER && reg_qty[ureg] < 0) /* Do not combine registers unless one fits within the other. */ || (offset > 0 && usize + offset > ssize) || (offset < 0 && usize + offset < ssize) /* Do not combine with a smaller already-assigned object if that smaller object is already combined with something bigger. */ || (ssize > usize && ureg >= FIRST_PSEUDO_REGISTER && usize < qty_size[reg_qty[ureg]]) /* Can't combine if SREG is not a register we can allocate. */ || (sreg >= FIRST_PSEUDO_REGISTER && reg_qty[sreg] == -1) /* Don't combine with a pseudo mentioned in a REG_NO_CONFLICT note. These have already been taken care of. This probably wouldn't combine anyway, but don't take any chances. */ || (ureg >= FIRST_PSEUDO_REGISTER && find_reg_note (insn, REG_NO_CONFLICT, usedreg)) /* Don't tie something to itself. In most cases it would make no difference, but it would screw up if the reg being tied to itself also dies in this insn. */ || ureg == sreg /* Don't try to connect two different hardware registers. */ || (ureg < FIRST_PSEUDO_REGISTER && sreg < FIRST_PSEUDO_REGISTER) /* Don't connect two different machine modes if they have different implications as to which registers may be used. */ || !MODES_TIEABLE_P (GET_MODE (usedreg), GET_MODE (setreg))) return 0; /* Now, if UREG is a hard reg and SREG is a pseudo, record the hard reg in qty_phys_sugg for the pseudo instead of tying them. Return "failure" so that the lifespan of UREG is terminated here; that way the two lifespans will be disjoint and nothing will prevent the pseudo reg from being given this hard reg. */ if (ureg < FIRST_PSEUDO_REGISTER) { /* Allocate a quantity number so we have a place to put our suggestions. */ if (reg_qty[sreg] == -2) reg_is_born (setreg, 2 * insn_number); if (reg_qty[sreg] >= 0) { if (may_save_copy && ! TEST_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[sreg]], ureg)) { SET_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[sreg]], ureg); qty_phys_num_copy_sugg[reg_qty[sreg]]++; } else if (! TEST_HARD_REG_BIT (qty_phys_sugg[reg_qty[sreg]], ureg)) { SET_HARD_REG_BIT (qty_phys_sugg[reg_qty[sreg]], ureg); qty_phys_num_sugg[reg_qty[sreg]]++; } } return 0; } /* Similarly for SREG a hard register and UREG a pseudo register. */ if (sreg < FIRST_PSEUDO_REGISTER) { if (may_save_copy && ! TEST_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[ureg]], sreg)) { SET_HARD_REG_BIT (qty_phys_copy_sugg[reg_qty[ureg]], sreg); qty_phys_num_copy_sugg[reg_qty[ureg]]++; } else if (! TEST_HARD_REG_BIT (qty_phys_sugg[reg_qty[ureg]], sreg)) { SET_HARD_REG_BIT (qty_phys_sugg[reg_qty[ureg]], sreg); qty_phys_num_sugg[reg_qty[ureg]]++; } return 0; } /* At this point we know that SREG and UREG are both pseudos. Do nothing if SREG already has a quantity or is a register that we don't allocate. */ if (reg_qty[sreg] >= -1 /* If we are not going to let any regs live across calls, don't tie a call-crossing reg to a non-call-crossing reg. */ || (current_function_has_nonlocal_label && ((reg_n_calls_crossed[ureg] > 0) != (reg_n_calls_crossed[sreg] > 0)))) return 0; /* We don't already know about SREG, so tie it to UREG if this is the last use of UREG, provided the classes they want are compatible. */ if ((already_dead || find_regno_note (insn, REG_DEAD, ureg)) && reg_meets_class_p (sreg, qty_min_class[reg_qty[ureg]])) { /* Add SREG to UREG's quantity. */ sqty = reg_qty[ureg]; reg_qty[sreg] = sqty; reg_offset[sreg] = reg_offset[ureg] + offset; reg_next_in_qty[sreg] = qty_first_reg[sqty]; qty_first_reg[sqty] = sreg; /* If SREG's reg class is smaller, set qty_min_class[SQTY]. */ update_qty_class (sqty, sreg); /* Update info about quantity SQTY. */ qty_n_calls_crossed[sqty] += reg_n_calls_crossed[sreg]; qty_n_refs[sqty] += reg_n_refs[sreg]; if (usize < ssize) { register int i; for (i = qty_first_reg[sqty]; i >= 0; i = reg_next_in_qty[i]) reg_offset[i] -= offset; qty_size[sqty] = ssize; qty_mode[sqty] = GET_MODE (setreg); } } else return 0; return 1;}/* Return 1 if the preferred class of REG allows it to be tied to a quantity or register whose class is CLASS. True if REG's reg class either contains or is contained in CLASS. */static intreg_meets_class_p (reg, class) int reg; enum reg_class class;{ register enum reg_class rclass = reg_preferred_class (reg); return (reg_class_subset_p (rclass, class) || reg_class_subset_p (class, rclass));}/* Return 1 if the two specified classes have registers in common. If CALL_SAVED, then consider only call-saved registers. */static intreg_classes_overlap_p (c1, c2, call_saved) register enum reg_class c1; register enum reg_class c2; int call_saved;{ HARD_REG_SET c; int i; COPY_HARD_REG_SET (c, reg_class_contents[(int) c1]); AND_HARD_REG_SET (c, reg_class_contents[(int) c2]); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (c, i) && (! call_saved || ! call_used_regs[i])) return 1; return 0;}/* Update the class of QTY assuming that REG is being tied to it. */static voidupdate_qty_class (qty, reg) int qty; int reg;{ enum reg_class rclass = reg_preferred_class (reg); if (reg_class_subset_p (rclass, qty_min_class[qty])) qty_min_class[qty] = rclass; rclass = reg_alternate_class (reg); if (reg_class_subset_p (rclass, qty_alternate_class[qty])) qty_alternate_class[qty] = rclass; if (reg_changes_size[reg]) qty_changes_size[qty] = 1;}/* Handle something which alters the value of an rtx REG. REG is whatever is set or clobbered. SETTER is the rtx that is modifying the register. If it is not really a register, we do nothing. The file-global variables `this_insn' and `this_insn_number' carry info from `block_alloc'. */static voidreg_is_set (reg, setter) rtx reg; rtx setter;{ /* Note that note_stores will only pass us a SUBREG if it is a SUBREG of a hard register. These may actually not exist any more. */ if (GET_CODE (reg) != SUBREG && GET_CODE (reg) != REG) return; /* Mark this register as being born. If it is used in a CLOBBER, mark it as being born halfway between the previous insn and this insn so that it conflicts with our inputs but not the outputs of the previous insn. */ reg_is_born (reg, 2 * this_insn_number - (GET_CODE (setter) == CLOBBER));}/* Handle beginning of the life of register REG. BIRTH is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -