📄 reload.c
字号:
for (i = 0; i < n_reloads; i++) if ((reg_class_subset_p (class, reload_reg_class[i]) || reg_class_subset_p (reload_reg_class[i], class)) /* If the existing reload has a register, it must fit our class. */ && (reload_reg_rtx[i] == 0 || TEST_HARD_REG_BIT (reg_class_contents[(int) class], true_regnum (reload_reg_rtx[i]))) && reload_strict_low[i] == strict_low && out == 0 && reload_out[i] == 0 && reload_in[i] != 0 && ((GET_CODE (in) == REG && (GET_CODE (reload_in[i]) == POST_INC || GET_CODE (reload_in[i]) == POST_DEC || GET_CODE (reload_in[i]) == PRE_INC || GET_CODE (reload_in[i]) == PRE_DEC) && MATCHES (XEXP (reload_in[i], 0), in)) || (GET_CODE (reload_in[i]) == REG && (GET_CODE (in) == POST_INC || GET_CODE (in) == POST_DEC || GET_CODE (in) == PRE_INC || GET_CODE (in) == PRE_DEC) && MATCHES (XEXP (in, 0), reload_in[i])))) { /* Make sure reload_in ultimately has the increment, not the plain register. */ if (GET_CODE (in) == REG) in = reload_in[i]; break; } if (i == n_reloads) {#ifdef HAVE_SECONDARY_RELOADS enum reg_class secondary_class = NO_REGS; enum reg_class secondary_out_class = NO_REGS; enum machine_mode secondary_mode = inmode; enum machine_mode secondary_out_mode = outmode; enum insn_code secondary_icode; enum insn_code secondary_out_icode = CODE_FOR_nothing; enum reg_class tertiary_class = NO_REGS; enum reg_class tertiary_out_class = NO_REGS; enum machine_mode tertiary_mode; enum machine_mode tertiary_out_mode; enum insn_code tertiary_icode; enum insn_code tertiary_out_icode = CODE_FOR_nothing; int tertiary_reload = -1; /* See if we need a secondary reload register to move between CLASS and IN or CLASS and OUT. Get the modes and icodes to use for each of them if so. */#ifdef SECONDARY_INPUT_RELOAD_CLASS if (in != 0) secondary_class = find_secondary_reload (in, class, inmode, 1, &secondary_icode, &secondary_mode, &tertiary_class, &tertiary_icode, &tertiary_mode);#endif#ifdef SECONDARY_OUTPUT_RELOAD_CLASS if (out != 0 && GET_CODE (out) != SCRATCH) secondary_out_class = find_secondary_reload (out, class, outmode, 0, &secondary_out_icode, &secondary_out_mode, &tertiary_out_class, &tertiary_out_icode, &tertiary_out_mode);#endif /* We can only record one secondary and one tertiary reload. If both IN and OUT need secondary reloads, we can only make an in-out reload if neither need an insn and if the classes are compatible. */ if (secondary_class != NO_REGS && secondary_out_class != NO_REGS && reg_class_subset_p (secondary_out_class, secondary_class)) secondary_class = secondary_out_class; if (secondary_class != NO_REGS && secondary_out_class != NO_REGS && (! reg_class_subset_p (secondary_class, secondary_out_class) || secondary_icode != CODE_FOR_nothing || secondary_out_icode != CODE_FOR_nothing)) { push_reload (NULL_RTX, out, NULL_PTR, outloc, class, VOIDmode, outmode, strict_low, optional, needed_for); out = 0; outloc = 0; outmode = VOIDmode; } /* If we need a secondary reload for OUT but not IN, copy the information. */ if (secondary_class == NO_REGS && secondary_out_class != NO_REGS) { secondary_class = secondary_out_class; secondary_icode = secondary_out_icode; tertiary_class = tertiary_out_class; tertiary_icode = tertiary_out_icode; tertiary_mode = tertiary_out_mode; } if (secondary_class != NO_REGS) { /* If we need a tertiary reload, see if we have one we can reuse or else make one. */ if (tertiary_class != NO_REGS) { for (tertiary_reload = 0; tertiary_reload < n_reloads; tertiary_reload++) if (reload_secondary_p[tertiary_reload] && (reg_class_subset_p (tertiary_class, reload_reg_class[tertiary_reload]) || reg_class_subset_p (reload_reg_class[tertiary_reload], tertiary_class)) && ((reload_inmode[tertiary_reload] == tertiary_mode) || reload_inmode[tertiary_reload] == VOIDmode) && ((reload_outmode[tertiary_reload] == tertiary_mode) || reload_outmode[tertiary_reload] == VOIDmode) && (reload_secondary_icode[tertiary_reload] == CODE_FOR_nothing)) { if (tertiary_mode != VOIDmode) reload_inmode[tertiary_reload] = tertiary_mode; if (tertiary_out_mode != VOIDmode) reload_outmode[tertiary_reload] = tertiary_mode; if (reg_class_subset_p (tertiary_class, reload_reg_class[tertiary_reload])) reload_reg_class[tertiary_reload] = tertiary_class; if (reload_needed_for[tertiary_reload] != needed_for) reload_needed_for_multiple[tertiary_reload] = 1; reload_optional[tertiary_reload] &= optional; reload_secondary_p[tertiary_reload] = 1; } if (tertiary_reload == n_reloads) { /* We need to make a new tertiary reload for this register class. */ reload_in[tertiary_reload] = reload_out[tertiary_reload] = 0; reload_reg_class[tertiary_reload] = tertiary_class; reload_inmode[tertiary_reload] = tertiary_mode; reload_outmode[tertiary_reload] = tertiary_mode; reload_reg_rtx[tertiary_reload] = 0; reload_optional[tertiary_reload] = optional; reload_inc[tertiary_reload] = 0; reload_strict_low[tertiary_reload] = 0; /* Maybe we could combine these, but it seems too tricky. */ reload_nocombine[tertiary_reload] = 1; reload_in_reg[tertiary_reload] = 0; reload_needed_for[tertiary_reload] = needed_for; reload_needed_for_multiple[tertiary_reload] = 0; reload_secondary_reload[tertiary_reload] = -1; reload_secondary_icode[tertiary_reload] = CODE_FOR_nothing; reload_secondary_p[tertiary_reload] = 1; n_reloads++; i = n_reloads; } } /* See if we can reuse an existing secondary reload. */ for (secondary_reload = 0; secondary_reload < n_reloads; secondary_reload++) if (reload_secondary_p[secondary_reload] && (reg_class_subset_p (secondary_class, reload_reg_class[secondary_reload]) || reg_class_subset_p (reload_reg_class[secondary_reload], secondary_class)) && ((reload_inmode[secondary_reload] == secondary_mode) || reload_inmode[secondary_reload] == VOIDmode) && ((reload_outmode[secondary_reload] == secondary_out_mode) || reload_outmode[secondary_reload] == VOIDmode) && reload_secondary_reload[secondary_reload] == tertiary_reload && reload_secondary_icode[secondary_reload] == tertiary_icode) { if (secondary_mode != VOIDmode) reload_inmode[secondary_reload] = secondary_mode; if (secondary_out_mode != VOIDmode) reload_outmode[secondary_reload] = secondary_out_mode; if (reg_class_subset_p (secondary_class, reload_reg_class[secondary_reload])) reload_reg_class[secondary_reload] = secondary_class; if (reload_needed_for[secondary_reload] != needed_for) reload_needed_for_multiple[secondary_reload] = 1; reload_optional[secondary_reload] &= optional; reload_secondary_p[secondary_reload] = 1; } if (secondary_reload == n_reloads) { /* We need to make a new secondary reload for this register class. */ reload_in[secondary_reload] = reload_out[secondary_reload] = 0; reload_reg_class[secondary_reload] = secondary_class; reload_inmode[secondary_reload] = secondary_mode; reload_outmode[secondary_reload] = secondary_out_mode; reload_reg_rtx[secondary_reload] = 0; reload_optional[secondary_reload] = optional; reload_inc[secondary_reload] = 0; reload_strict_low[secondary_reload] = 0; /* Maybe we could combine these, but it seems too tricky. */ reload_nocombine[secondary_reload] = 1; reload_in_reg[secondary_reload] = 0; reload_needed_for[secondary_reload] = needed_for; reload_needed_for_multiple[secondary_reload] = 0; reload_secondary_reload[secondary_reload] = tertiary_reload; reload_secondary_icode[secondary_reload] = tertiary_icode; reload_secondary_p[secondary_reload] = 1; n_reloads++; i = n_reloads;#ifdef SECONDARY_MEMORY_NEEDED /* If we need a memory location to copy between the two reload regs, set it up now. */ if (in != 0 && secondary_icode == CODE_FOR_nothing && SECONDARY_MEMORY_NEEDED (secondary_class, class, inmode)) get_secondary_mem (in, inmode); if (out != 0 && secondary_icode == CODE_FOR_nothing && SECONDARY_MEMORY_NEEDED (class, secondary_class, outmode)) get_secondary_mem (out, outmode);#endif } }#endif /* We found no existing reload suitable for re-use. So add an additional reload. */ reload_in[i] = in; reload_out[i] = out; reload_reg_class[i] = class; reload_inmode[i] = inmode; reload_outmode[i] = outmode; reload_reg_rtx[i] = 0; reload_optional[i] = optional; reload_inc[i] = 0; reload_strict_low[i] = strict_low; reload_nocombine[i] = 0; reload_in_reg[i] = inloc ? *inloc : 0; reload_needed_for[i] = needed_for; reload_needed_for_multiple[i] = 0; reload_secondary_reload[i] = secondary_reload; reload_secondary_icode[i] = secondary_icode; reload_secondary_p[i] = 0; n_reloads++;#ifdef SECONDARY_MEMORY_NEEDED /* If a memory location is needed for the copy, make one. */ if (in != 0 && GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)), class, inmode)) get_secondary_mem (in, inmode); if (out != 0 && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)), outmode)) get_secondary_mem (out, outmode);#endif } else { /* We are reusing an existing reload, but we may have additional information for it. For example, we may now have both IN and OUT while the old one may have just one of them. */ if (inmode != VOIDmode) reload_inmode[i] = inmode; if (outmode != VOIDmode) reload_outmode[i] = outmode; if (in != 0) reload_in[i] = in; if (out != 0) reload_out[i] = out; if (reg_class_subset_p (class, reload_reg_class[i])) reload_reg_class[i] = class; reload_optional[i] &= optional; if (reload_needed_for[i] != needed_for) reload_needed_for_multiple[i] = 1; } /* If the ostensible rtx being reload differs from the rtx found in the location to substitute, this reload is not safe to combine because we cannot reliably tell whether it appears in the insn. */ if (in != 0 && in != *inloc) reload_nocombine[i] = 1;#if 0 /* This was replaced by changes in find_reloads_address_1 and the new function inc_for_reload, which go with a new meaning of reload_inc. */ /* If this is an IN/OUT reload in an insn that sets the CC, it must be for an autoincrement. It doesn't work to store the incremented value after the insn because that would clobber the CC. So we must do the increment of the value reloaded from, increment it, store it back, then decrement again. */ if (out != 0 && sets_cc0_p (PATTERN (this_insn))) { out = 0; reload_out[i] = 0; reload_inc[i] = find_inc_amount (PATTERN (this_insn), in); /* If we did not find a nonzero amount-to-increment-by, that contradicts the belief that IN is being incremented in an address in this insn. */ if (reload_inc[i] == 0) abort (); }#endif /* If we will replace IN and OUT with the reload-reg, record where they are located so that substitution need not do a tree walk. */ if (replace_reloads) { if (inloc != 0) { register struct replacement *r = &replacements[n_replacements++]; r->what = i; r->subreg_loc = in_subreg_loc; r->where = inloc; r->mode = inmode; } if (outloc != 0 && outloc != inloc) { register struct replacement *r = &replacements[n_replacements++]; r->what = i; r->where = outloc; r->subreg_loc = out_subreg_loc; r->mode = outmode; } } /* If this reload is just being introduced and it has both an incoming quantity and an outgoing quantity that are supposed to be made to match, see if either one of the two can serve as the place to reload into. If one of them is acceptable, set reload_reg_rtx[i] to that one. */ if (in != 0 && out != 0 && in != out && reload_reg_rtx[i] == 0) { reload_reg_rtx[i] = find_dummy_reload (in, out, inloc, outloc, reload_reg_class[i], i); /* If the outgoing register already contains the same value as the incoming one, we can dispense with loading it. The easiest way to tell the caller that is to give a phony value for the incoming operand (same as outgoing one). */ if (reload_reg_rtx[i] == out && (GET_CODE (in) == REG || CONSTANT_P (in)) && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out), static_reload_reg_p, i, inmode)) reload_in[i] = out; } /* If this is an input reload and the operand contains a register that dies in this insn and is used nowhere else, see if it is the right class to be used for this reload. Use it if so. (This occurs most commonly in the case of paradoxical SUBREGs and in-out reloads). We cannot do this if it is also an output reload that mentions the register unless the output is a SUBREG that clobbers an entire register. Note that the operand might be one of the spill regs, if it is a pseudo reg and we are in a block where spilling has not taken place. But if there is no spilling in this block, that is OK. An explicitly used hard reg cannot be a spill reg. */ if (reload_reg_rtx[i] == 0 && in != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -