📄 reload1.c
字号:
{ case RELOAD_OTHER: case RELOAD_FOR_OUTPUT: case RELOAD_FOR_INPUT: this_needs = insn_needs; this_groups = insn_groups; this_total_groups = &insn_total_groups; break; case RELOAD_FOR_INPUT_RELOAD_ADDRESS: this_needs = insn_needs_for_inputs; this_groups = insn_groups_for_inputs; this_total_groups = &insn_total_groups_for_inputs; break; case RELOAD_FOR_OUTPUT_RELOAD_ADDRESS: this_needs = insn_needs_for_outputs; this_groups = insn_groups_for_outputs; this_total_groups = &insn_total_groups_for_outputs; break; case RELOAD_FOR_OPERAND_ADDRESS: this_needs = insn_needs_for_operands; this_groups = insn_groups_for_operands; this_total_groups = &insn_total_groups_for_operands; break; } mode = reload_inmode[i]; if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode)) mode = reload_outmode[i]; size = CLASS_MAX_NREGS (class, mode); if (size > 1) { enum machine_mode other_mode, allocate_mode; /* Count number of groups needed separately from number of individual regs needed. */ this_groups[(int) class]++; p = reg_class_superclasses[(int) class]; while (*p != LIM_REG_CLASSES) this_groups[(int) *p++]++; (*this_total_groups)++; /* Record size and mode of a group of this class. */ /* If more than one size group is needed, make all groups the largest needed size. */ if (group_size[(int) class] < size) { other_mode = group_mode[(int) class]; allocate_mode = mode; group_size[(int) class] = size; group_mode[(int) class] = mode; } else { other_mode = mode; allocate_mode = group_mode[(int) class]; } /* Crash if two dissimilar machine modes both need groups of consecutive regs of the same class. */ if (other_mode != VOIDmode && other_mode != allocate_mode && ! modes_equiv_for_class_p (allocate_mode, other_mode, class)) abort (); } else if (size == 1) { this_needs[(int) class] += 1; p = reg_class_superclasses[(int) class]; while (*p != LIM_REG_CLASSES) this_needs[(int) *p++] += 1; } else abort (); } /* All reloads have been counted for this insn; now merge the various times of use. This sets insn_needs, etc., to the maximum total number of registers needed at any point in this insn. */ for (i = 0; i < N_REG_CLASSES; i++) { int this_max; this_max = insn_needs_for_inputs[i]; if (insn_needs_for_outputs[i] > this_max) this_max = insn_needs_for_outputs[i]; if (insn_needs_for_operands[i] > this_max) this_max = insn_needs_for_operands[i]; insn_needs[i] += this_max; this_max = insn_groups_for_inputs[i]; if (insn_groups_for_outputs[i] > this_max) this_max = insn_groups_for_outputs[i]; if (insn_groups_for_operands[i] > this_max) this_max = insn_groups_for_operands[i]; insn_groups[i] += this_max; } insn_total_groups += MAX (insn_total_groups_for_inputs, MAX (insn_total_groups_for_outputs, insn_total_groups_for_operands)); /* If this is a CALL_INSN and caller-saves will need a spill register, act as if the spill register is needed for this insn. However, the spill register can be used by any reload of this insn, so we only need do something if no need for that class has been recorded. The assumption that every CALL_INSN will trigger a caller-save is highly conservative, however, the number of cases where caller-saves will need a spill register but a block containing a CALL_INSN won't need a spill register of that class should be quite rare. If a group is needed, the size and mode of the group will have been set up at the beginning of this loop. */ if (GET_CODE (insn) == CALL_INSN && caller_save_spill_class != NO_REGS) { int *caller_save_needs = (caller_save_group_size > 1 ? insn_groups : insn_needs); if (caller_save_needs[(int) caller_save_spill_class] == 0) { register enum reg_class *p = reg_class_superclasses[(int) caller_save_spill_class]; caller_save_needs[(int) caller_save_spill_class]++; while (*p != LIM_REG_CLASSES) caller_save_needs[(int) *p++] += 1; } if (caller_save_group_size > 1) insn_total_groups = MAX (insn_total_groups, 1); /* Show that this basic block will need a register of this class. */ if (global && ! (basic_block_needs[(int) caller_save_spill_class] [this_block])) { basic_block_needs[(int) caller_save_spill_class] [this_block] = 1; new_basic_block_needs = 1; } }#ifdef SMALL_REGISTER_CLASSES /* If this insn stores the value of a function call, and that value is in a register that has been spilled, and if the insn needs a reload in a class that might use that register as the reload register, then add add an extra need in that class. This makes sure we have a register available that does not overlap the return value. */ if (avoid_return_reg) { int regno = REGNO (avoid_return_reg); int nregs = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg)); int r; int inc_groups = 0; for (r = regno; r < regno + nregs; r++) if (spill_reg_order[r] >= 0) for (i = 0; i < N_REG_CLASSES; i++) if (TEST_HARD_REG_BIT (reg_class_contents[i], r)) { if (insn_needs[i] > 0) insn_needs[i]++; if (insn_groups[i] > 0 && nregs > 1) inc_groups = 1; } if (inc_groups) insn_groups[i]++; }#endif /* SMALL_REGISTER_CLASSES */ /* For each class, collect maximum need of any insn. */ for (i = 0; i < N_REG_CLASSES; i++) { if (max_needs[i] < insn_needs[i]) { max_needs[i] = insn_needs[i]; max_needs_insn[i] = insn; } if (max_groups[i] < insn_groups[i]) { max_groups[i] = insn_groups[i]; max_groups_insn[i] = insn; } if (insn_total_groups > 0) if (max_nongroups[i] < insn_needs[i]) { max_nongroups[i] = insn_needs[i]; max_nongroups_insn[i] = insn; } } } /* Note that there is a continue statement above. */ } /* If we allocated any new memory locations, make another pass since it might have changed elimination offsets. */ if (starting_frame_size != get_frame_size ()) something_changed = 1; if (dumpfile) for (i = 0; i < N_REG_CLASSES; i++) { if (max_needs[i] > 0) fprintf (dumpfile, ";; Need %d reg%s of class %s (for insn %d).\n", max_needs[i], max_needs[i] == 1 ? "" : "s", reg_class_names[i], INSN_UID (max_needs_insn[i])); if (max_nongroups[i] > 0) fprintf (dumpfile, ";; Need %d nongroup reg%s of class %s (for insn %d).\n", max_nongroups[i], max_nongroups[i] == 1 ? "" : "s", reg_class_names[i], INSN_UID (max_nongroups_insn[i])); if (max_groups[i] > 0) fprintf (dumpfile, ";; Need %d group%s (%smode) of class %s (for insn %d).\n", max_groups[i], max_groups[i] == 1 ? "" : "s", mode_name[(int) group_mode[i]], reg_class_names[i], INSN_UID (max_groups_insn[i])); } /* If we have caller-saves, set up the save areas and see if caller-save will need a spill register. */ if (caller_save_needed && ! setup_save_areas (&something_changed) && caller_save_spill_class == NO_REGS) { /* The class we will need depends on whether the machine supports the sum of two registers for an address; see find_address_reloads for details. */ caller_save_spill_class = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS; caller_save_group_size = CLASS_MAX_NREGS (caller_save_spill_class, Pmode); something_changed = 1; } /* Now deduct from the needs for the registers already available (already spilled). */ CLEAR_HARD_REG_SET (counted_for_groups); CLEAR_HARD_REG_SET (counted_for_nongroups); /* First find all regs alone in their class and count them (if desired) for non-groups. We would be screwed if a group took the only reg in a class for which a non-group reload is needed. (Note there is still a bug; if a class has 2 regs, both could be stolen by groups and we would lose the same way. With luck, no machine will need a nongroup in a 2-reg class.) */ for (i = 0; i < n_spills; i++) { register enum reg_class *p; class = (int) REGNO_REG_CLASS (spill_regs[i]); if (reg_class_size[class] == 1 && max_nongroups[class] > 0) { max_needs[class]--; p = reg_class_superclasses[class]; while (*p != LIM_REG_CLASSES) max_needs[(int) *p++]--; SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]); max_nongroups[class]--; p = reg_class_superclasses[class]; while (*p != LIM_REG_CLASSES) { if (max_nongroups[(int) *p] > 0) SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]); max_nongroups[(int) *p++]--; } } } /* Now find all consecutive groups of spilled registers and mark each group off against the need for such groups. But don't count them against ordinary need, yet. */ count_possible_groups (group_size, group_mode, max_groups); /* Now count all spill regs against the individual need, This includes those counted above for groups, but not those previously counted for nongroups. Those that weren't counted_for_groups can also count against the not-in-group need. */ for (i = 0; i < n_spills; i++) { register enum reg_class *p; class = (int) REGNO_REG_CLASS (spill_regs[i]); /* Those counted at the beginning shouldn't be counted twice. */ if (! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i])) { max_needs[class]--; p = reg_class_superclasses[class]; while (*p != LIM_REG_CLASSES) max_needs[(int) *p++]--; if (! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[i])) { if (max_nongroups[class] > 0) SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]); max_nongroups[class]--; p = reg_class_superclasses[class]; while (*p != LIM_REG_CLASSES) { if (max_nongroups[(int) *p] > 0) SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]); max_nongroups[(int) *p++]--; } } } } /* See if anything that happened changes which eliminations are valid. For example, on the Sparc, whether or not the frame pointer can be eliminated can depend on what registers have been used. We need not check some conditions again (such as flag_omit_frame_pointer) since they can't have changed. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) if ((ep->from == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)#ifdef ELIMINABLE_REGS || ! CAN_ELIMINATE (ep->from, ep->to)#endif ) ep->can_eliminate = 0; /* Look for the case where we have discovered that we can't replace register A with register B and that means that we will now be trying to replace register A with register C. This means we can no longer replace register C with register B and we need to disable such an elimination, if it exists. This occurs often with A == ap, B == sp, and C == fp. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { struct elim_table *op; register int new_to = -1; if (! ep->can_eliminate && ep->can_eliminate_previous) { /* Find the current elimination for ep->from, if there is a new one. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -