📄 reload1.c
字号:
&& reg_classes_intersect_p (class, reload_reg_class[j])) { nongroup_need = 1; break; } /* Decide which time-of-use to count this reload for. */ switch (reload_when_needed[i]) { case RELOAD_OTHER: this_needs = &insn_needs.other; break; case RELOAD_FOR_INPUT: this_needs = &insn_needs.input; break; case RELOAD_FOR_OUTPUT: this_needs = &insn_needs.output; break; case RELOAD_FOR_INSN: this_needs = &insn_needs.insn; break; case RELOAD_FOR_OTHER_ADDRESS: this_needs = &insn_needs.other_addr; break; case RELOAD_FOR_INPUT_ADDRESS: this_needs = &insn_needs.in_addr[reload_opnum[i]]; break; case RELOAD_FOR_OUTPUT_ADDRESS: this_needs = &insn_needs.out_addr[reload_opnum[i]]; break; case RELOAD_FOR_OPERAND_ADDRESS: this_needs = &insn_needs.op_addr; break; case RELOAD_FOR_OPADDR_ADDR: this_needs = &insn_needs.op_addr_reload; break; } if (size > 1) { enum machine_mode other_mode, allocate_mode; /* Count number of groups needed separately from number of individual regs needed. */ this_needs->groups[(int) class]++; p = reg_class_superclasses[(int) class]; while (*p != LIM_REG_CLASSES) this_needs->groups[(int) *p++]++; /* 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)) fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class", insn); } else if (size == 1) { this_needs->regs[nongroup_need][(int) class] += 1; p = reg_class_superclasses[(int) class]; while (*p != LIM_REG_CLASSES) this_needs->regs[nongroup_need][(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 in_max, out_max; /* Compute normal and nongroup needs. */ for (j = 0; j <= 1; j++) { for (in_max = 0, out_max = 0, k = 0; k < reload_n_operands; k++) { in_max = MAX (in_max, insn_needs.in_addr[k].regs[j][i]); out_max = MAX (out_max, insn_needs.out_addr[k].regs[j][i]); } /* RELOAD_FOR_INSN reloads conflict with inputs, outputs, and operand addresses but not things used to reload them. Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads don't conflict with things needed to reload inputs or outputs. */ in_max = MAX (MAX (insn_needs.op_addr.regs[j][i], insn_needs.op_addr_reload.regs[j][i]), in_max); out_max = MAX (out_max, insn_needs.insn.regs[j][i]); insn_needs.input.regs[j][i] = MAX (insn_needs.input.regs[j][i] + insn_needs.op_addr.regs[j][i] + insn_needs.insn.regs[j][i], in_max + insn_needs.input.regs[j][i]); insn_needs.output.regs[j][i] += out_max; insn_needs.other.regs[j][i] += MAX (MAX (insn_needs.input.regs[j][i], insn_needs.output.regs[j][i]), insn_needs.other_addr.regs[j][i]); } /* Now compute group needs. */ for (in_max = 0, out_max = 0, j = 0; j < reload_n_operands; j++) { in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]); out_max = MAX (out_max, insn_needs.out_addr[j].groups[i]); } in_max = MAX (MAX (insn_needs.op_addr.groups[i], insn_needs.op_addr_reload.groups[i]), in_max); out_max = MAX (out_max, insn_needs.insn.groups[i]); insn_needs.input.groups[i] = MAX (insn_needs.input.groups[i] + insn_needs.op_addr.groups[i] + insn_needs.insn.groups[i], in_max + insn_needs.input.groups[i]); insn_needs.output.groups[i] += out_max; insn_needs.other.groups[i] += MAX (MAX (insn_needs.input.groups[i], insn_needs.output.groups[i]), insn_needs.other_addr.groups[i]); } /* 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) { /* See if this register would conflict with any reload that needs a group. */ int nongroup_need = 0; int *caller_save_needs; for (j = 0; j < n_reloads; j++) if ((CLASS_MAX_NREGS (reload_reg_class[j], (GET_MODE_SIZE (reload_outmode[j]) > GET_MODE_SIZE (reload_inmode[j])) ? reload_outmode[j] : reload_inmode[j]) > 1) && reg_classes_intersect_p (caller_save_spill_class, reload_reg_class[j])) { nongroup_need = 1; break; } caller_save_needs = (caller_save_group_size > 1 ? insn_needs.other.groups : insn_needs.other.regs[nongroup_need]); 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; } /* 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 basic_needs[N_REG_CLASSES], basic_groups[N_REG_CLASSES]; /* First compute the "basic needs", which counts a need only in the smallest class in which it is required. */ bcopy ((char *) insn_needs.other.regs[0], (char *) basic_needs, sizeof basic_needs); bcopy ((char *) insn_needs.other.groups, (char *) basic_groups, sizeof basic_groups); for (i = 0; i < N_REG_CLASSES; i++) { enum reg_class *p; if (basic_needs[i] >= 0) for (p = reg_class_superclasses[i]; *p != LIM_REG_CLASSES; p++) basic_needs[(int) *p] -= basic_needs[i]; if (basic_groups[i] >= 0) for (p = reg_class_superclasses[i]; *p != LIM_REG_CLASSES; p++) basic_groups[(int) *p] -= basic_groups[i]; } /* Now count extra regs if there might be a conflict with the return value register. */ 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 (basic_needs[i] > 0) { enum reg_class *p; insn_needs.other.regs[0][i]++; p = reg_class_superclasses[i]; while (*p != LIM_REG_CLASSES) insn_needs.other.regs[0][(int) *p++]++; } if (basic_groups[i] > 0) { enum reg_class *p; insn_needs.other.groups[i]++; p = reg_class_superclasses[i]; while (*p != LIM_REG_CLASSES) insn_needs.other.groups[(int) *p++]++; } } }#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.other.regs[0][i]) { max_needs[i] = insn_needs.other.regs[0][i]; max_needs_insn[i] = insn; } if (max_groups[i] < insn_needs.other.groups[i]) { max_groups[i] = insn_needs.other.groups[i]; max_groups_insn[i] = insn; } if (max_nongroups[i] < insn_needs.other.regs[1][i]) { max_nongroups[i] = insn_needs.other.regs[1][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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -