📄 combine.c
字号:
/* If we couldn't eliminate a field assignment, we can't combine. */ || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART /* Don't combine with an insn that sets a register to itself if it has a REG_EQUAL note. This may be part of a REG_NO_CONFLICT sequence. */ || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX)) /* Can't merge a function call. */ || GET_CODE (src) == CALL /* Don't substitute into an incremented register. */ || FIND_REG_INC_NOTE (i3, dest) || (succ && FIND_REG_INC_NOTE (succ, dest)) /* Don't combine the end of a libcall into anything. */ || find_reg_note (insn, REG_RETVAL, NULL_RTX) /* Make sure that DEST is not used after SUCC but before I3. */ || (succ && ! all_adjacent && reg_used_between_p (dest, succ, i3)) /* Make sure that the value that is to be substituted for the register does not use any registers whose values alter in between. However, If the insns are adjacent, a use can't cross a set even though we think it might (this can happen for a sequence of insns each setting the same destination; reg_last_set of that register might point to a NOTE). Also, don't move a volatile asm across any other insns. */ || (! all_adjacent && (use_crosses_set_p (src, INSN_CUID (insn)) || (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src)))) /* If there is a REG_NO_CONFLICT note for DEST in I3 or SUCC, we get better register allocation by not doing the combine. */ || find_reg_note (i3, REG_NO_CONFLICT, dest) || (succ && find_reg_note (succ, REG_NO_CONFLICT, dest)) /* Don't combine across a CALL_INSN, because that would possibly change whether the life span of some REGs crosses calls or not, and it is a pain to update that information. Exception: if source is a constant, moving it later can't hurt. Accept that special case, because it helps -fforce-addr a lot. */ || (INSN_CUID (insn) < last_call_cuid && ! CONSTANT_P (src))) return 0; /* DEST must either be a REG or CC0. */ if (GET_CODE (dest) == REG) { /* If register alignment is being enforced for multi-word items in all cases except for parameters, it is possible to have a register copy insn referencing a hard register that is not allowed to contain the mode being copied and which would not be valid as an operand of most insns. Eliminate this problem by not combining with such an insn. Also, on some machines we don't want to extend the life of a hard register. */ if (GET_CODE (src) == REG && ((REGNO (dest) < FIRST_PSEUDO_REGISTER && ! HARD_REGNO_MODE_OK (REGNO (dest), GET_MODE (dest)))#ifdef SMALL_REGISTER_CLASSES /* Don't extend the life of a hard register. */ || REGNO (src) < FIRST_PSEUDO_REGISTER#else || (REGNO (src) < FIRST_PSEUDO_REGISTER && ! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)))#endif )) return 0; } else if (GET_CODE (dest) != CC0) return 0; /* Don't substitute for a register intended as a clobberable operand. Similarly, don't substitute an expression containing a register that will be clobbered in I3. */ if (GET_CODE (PATTERN (i3)) == PARALLEL) for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--) if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER && (reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), src) || rtx_equal_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), dest))) return 0; /* If INSN contains anything volatile, or is an `asm' (whether volatile or not), reject, unless nothing volatile comes between it and I3, with the exception of SUCC. */ if (GET_CODE (src) == ASM_OPERANDS || volatile_refs_p (src)) for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p)) if (GET_RTX_CLASS (GET_CODE (p)) == 'i' && p != succ && volatile_refs_p (PATTERN (p))) return 0; /* If INSN or I2 contains an autoincrement or autodecrement, make sure that register is not used between there and I3, and not already used in I3 either. Also insist that I3 not be a jump; if it were one and the incremented register were spilled, we would lose. */#ifdef AUTO_INC_DEC for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_INC && (GET_CODE (i3) == JUMP_INSN || reg_used_between_p (XEXP (link, 0), insn, i3) || reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i3)))) return 0;#endif#ifdef HAVE_cc0 /* Don't combine an insn that follows a CC0-setting insn. An insn that uses CC0 must not be separated from the one that sets it. We do, however, allow I2 to follow a CC0-setting insn if that insn is passed as I1; in that case it will be deleted also. We also allow combining in this case if all the insns are adjacent because that would leave the two CC0 insns adjacent as well. It would be more logical to test whether CC0 occurs inside I1 or I2, but that would be much slower, and this ought to be equivalent. */ p = prev_nonnote_insn (insn); if (p && p != pred && GET_CODE (p) == INSN && sets_cc0_p (PATTERN (p)) && ! all_adjacent) return 0;#endif /* If we get here, we have passed all the tests and the combination is to be allowed. */ *pdest = dest; *psrc = src; return 1;}/* LOC is the location within I3 that contains its pattern or the component of a PARALLEL of the pattern. We validate that it is valid for combining. One problem is if I3 modifies its output, as opposed to replacing it entirely, we can't allow the output to contain I2DEST or I1DEST as doing so would produce an insn that is not equivalent to the original insns. Consider: (set (reg:DI 101) (reg:DI 100)) (set (subreg:SI (reg:DI 101) 0) <foo>) This is NOT equivalent to: (parallel [(set (subreg:SI (reg:DI 100) 0) <foo>) (set (reg:DI 101) (reg:DI 100))]) Not only does this modify 100 (in which case it might still be valid if 100 were dead in I2), it sets 101 to the ORIGINAL value of 100. We can also run into a problem if I2 sets a register that I1 uses and I1 gets directly substituted into I3 (not via I2). In that case, we would be getting the wrong value of I2DEST into I3, so we must reject the combination. This case occurs when I2 and I1 both feed into I3, rather than when I1 feeds into I2, which feeds into I3. If I1_NOT_IN_SRC is non-zero, it means that finding I1 in the source of a SET must prevent combination from occurring. On machines where SMALL_REGISTER_CLASSES is defined, we don't combine if the destination of a SET is a hard register. Before doing the above check, we first try to expand a field assignment into a set of logical operations. If PI3_DEST_KILLED is non-zero, it is a pointer to a location in which we place a register that is both set and used within I3. If more than one such register is detected, we fail. Return 1 if the combination is valid, zero otherwise. */static intcombinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed) rtx i3; rtx *loc; rtx i2dest; rtx i1dest; int i1_not_in_src; rtx *pi3dest_killed;{ rtx x = *loc; if (GET_CODE (x) == SET) { rtx set = expand_field_assignment (x); rtx dest = SET_DEST (set); rtx src = SET_SRC (set); rtx inner_dest = dest, inner_src = src; SUBST (*loc, set); while (GET_CODE (inner_dest) == STRICT_LOW_PART || GET_CODE (inner_dest) == SUBREG || GET_CODE (inner_dest) == ZERO_EXTRACT) inner_dest = XEXP (inner_dest, 0); /* We probably don't need this any more now that LIMIT_RELOAD_CLASS was added. */#if 0 while (GET_CODE (inner_src) == STRICT_LOW_PART || GET_CODE (inner_src) == SUBREG || GET_CODE (inner_src) == ZERO_EXTRACT) inner_src = XEXP (inner_src, 0); /* If it is better that two different modes keep two different pseudos, avoid combining them. This avoids producing the following pattern on a 386: (set (subreg:SI (reg/v:QI 21) 0) (lshiftrt:SI (reg/v:SI 20) (const_int 24))) If that were made, reload could not handle the pair of reg 20/21, since it would try to get any GENERAL_REGS but some of them don't handle QImode. */ if (rtx_equal_p (inner_src, i2dest) && GET_CODE (inner_dest) == REG && ! MODES_TIEABLE_P (GET_MODE (i2dest), GET_MODE (inner_dest))) return 0;#endif /* Check for the case where I3 modifies its output, as discussed above. */ if ((inner_dest != dest && (reg_overlap_mentioned_p (i2dest, inner_dest) || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest)))) /* This is the same test done in can_combine_p except that we allow a hard register with SMALL_REGISTER_CLASSES if SRC is a CALL operation. */ || (GET_CODE (inner_dest) == REG && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER#ifdef SMALL_REGISTER_CLASSES && GET_CODE (src) != CALL#else && ! HARD_REGNO_MODE_OK (REGNO (inner_dest), GET_MODE (inner_dest))#endif ) || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src))) return 0; /* If DEST is used in I3, it is being killed in this insn, so record that for later. */ if (pi3dest_killed && GET_CODE (dest) == REG && reg_referenced_p (dest, PATTERN (i3))) { if (*pi3dest_killed) return 0; *pi3dest_killed = dest; } } else if (GET_CODE (x) == PARALLEL) { int i; for (i = 0; i < XVECLEN (x, 0); i++) if (! combinable_i3pat (i3, &XVECEXP (x, 0, i), i2dest, i1dest, i1_not_in_src, pi3dest_killed)) return 0; } return 1;}/* Try to combine the insns I1 and I2 into I3. Here I1 and I2 appear earlier than I3. I1 can be zero; then we combine just I2 into I3. It we are combining three insns and the resulting insn is not recognized, try splitting it into two insns. If that happens, I2 and I3 are retained and I1 is pseudo-deleted by turning it into a NOTE. Otherwise, I1 and I2 are pseudo-deleted. If we created two insns, return I2; otherwise return I3. Return 0 if the combination does not work. Then nothing is changed. */static rtxtry_combine (i3, i2, i1) register rtx i3, i2, i1;{ /* New patterns for I3 and I3, respectively. */ rtx newpat, newi2pat = 0; /* Indicates need to preserve SET in I1 or I2 in I3 if it is not dead. */ int added_sets_1, added_sets_2; /* Total number of SETs to put into I3. */ int total_sets; /* Nonzero is I2's body now appears in I3. */ int i2_is_used; /* INSN_CODEs for new I3, new I2, and user of condition code. */ int insn_code_number, i2_code_number, other_code_number; /* Contains I3 if the destination of I3 is used in its source, which means that the old life of I3 is being killed. If that usage is placed into I2 and not in I3, a REG_DEAD note must be made. */ rtx i3dest_killed = 0; /* SET_DEST and SET_SRC of I2 and I1. */ rtx i2dest, i2src, i1dest = 0, i1src = 0; /* PATTERN (I2), or a copy of it in certain cases. */ rtx i2pat; /* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC. */ int i2dest_in_i2src, i1dest_in_i1src = 0, i2dest_in_i1src = 0; int i1_feeds_i3 = 0; /* Notes that must be added to REG_NOTES in I3 and I2. */ rtx new_i3_notes, new_i2_notes; int maxreg; rtx temp; register rtx link; int i; /* If any of I1, I2, and I3 isn't really an insn, we can't do anything. This can occur when flow deletes an insn that it has merged into an auto-increment address. We also can't do anything if I3 has a REG_LIBCALL note since we don't want to disrupt the contiguity of a libcall. */ if (GET_RTX_CLASS (GET_CODE (i3)) != 'i' || GET_RTX_CLASS (GET_CODE (i2)) != 'i' || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i') || find_reg_note (i3, REG_LIBCALL, NULL_RTX)) return 0; combine_attempts++; undobuf.num_undo = previous_num_undos = 0; undobuf.other_insn = 0; /* Save the current high-water-mark so we can free storage if we didn't accept this combination. */ undobuf.storage = (char *) oballoc (0); /* If I1 and I2 both feed I3, they can be in any order. To simplify the code below, set I1 to be the earlier of the two insns. */ if (i1 && INSN_CUID (i1) > INSN_CUID (i2)) temp = i1, i1 = i2, i2 = temp; /* First check for one important special-case that the code below will not handle. Namely, the case where I1 is zero, I2 has multiple sets, and I3 is a SET whose SET_SRC is a SET_DEST in I2. In that case, we may be able to replace that destination with the destination of I3. This occurs in the common code where we compute both a quotient and remainder into a structure, in which case we want to do the computation directly into the structure to avoid register-register copies. We make very conservative checks below and only try to handle the most common cases of this. For example, we only handle the case where I2 and I3 are adjacent to avoid making difficult register usage tests. */ if (i1 == 0 && GET_CODE (i3) == INSN && GET_CODE (PATTERN (i3)) == SET && GET_CODE (SET_SRC (PATTERN (i3))) == REG && REGNO (SET_SRC (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER#ifdef SMALL_REGISTER_CLASSES && (GET_CODE (SET_DEST (PATTERN (i3))) != REG || REGNO (SET_DEST (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER)#endif && find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3))) && GET_CODE (PATTERN (i2)) == PARALLEL && ! side_effects_p (SET_DEST (PATTERN (i3))) /* If the dest of I3 is a ZERO_EXTRACT or STRICT_LOW_PART, the code below would need to check what is inside (and reg_overlap_mentioned_p doesn't support those codes anyway). Don't allow those destinations;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -