📄 combine.c
字号:
}/* Called via note_stores. If X is a pseudo that is narrower than HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero. If we are setting only a portion of X and we can't figure out what portion, assume all bits will be used since we don't know what will be happening. Similarly, set how many bits of X are known to be copies of the sign bit at all locations in the function. This is the smallest number implied by any set of X. */static voidset_nonzero_bits_and_sign_copies (x, set) rtx x; rtx set;{ int num; if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER /* If this register is undefined at the start of the file, we can't say what its contents were. */ && ! REGNO_REG_SET_P (basic_block_live_at_start[0], REGNO (x)) && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT) { if (set == 0 || GET_CODE (set) == CLOBBER) { reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x)); reg_sign_bit_copies[REGNO (x)] = 1; return; } /* If this is a complex assignment, see if we can convert it into a simple assignment. */ set = expand_field_assignment (set); /* If this is a simple assignment, or we have a paradoxical SUBREG, set what we know about X. */ if (SET_DEST (set) == x || (GET_CODE (SET_DEST (set)) == SUBREG && (GET_MODE_SIZE (GET_MODE (SET_DEST (set))) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (set))))) && SUBREG_REG (SET_DEST (set)) == x)) { rtx src = SET_SRC (set);#ifdef SHORT_IMMEDIATES_SIGN_EXTEND /* If X is narrower than a word and SRC is a non-negative constant that would appear negative in the mode of X, sign-extend it for use in reg_nonzero_bits because some machines (maybe most) will actually do the sign-extension and this is the conservative approach. ??? For 2.5, try to tighten up the MD files in this regard instead of this kludge. */ if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD && GET_CODE (src) == CONST_INT && INTVAL (src) > 0 && 0 != (INTVAL (src) & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (GET_MODE (x)) - 1)))) src = GEN_INT (INTVAL (src) | ((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (GET_MODE (x))));#endif reg_nonzero_bits[REGNO (x)] |= nonzero_bits (src, nonzero_bits_mode); num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); if (reg_sign_bit_copies[REGNO (x)] == 0 || reg_sign_bit_copies[REGNO (x)] > num) reg_sign_bit_copies[REGNO (x)] = num; } else { reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x)); reg_sign_bit_copies[REGNO (x)] = 1; } }}/* See if INSN can be combined into I3. PRED and SUCC are optionally insns that were previously combined into I3 or that will be combined into the merger of INSN and I3. Return 0 if the combination is not allowed for any reason. If the combination is allowed, *PDEST will be set to the single destination of INSN and *PSRC to the single source, and this function will return 1. */static intcan_combine_p (insn, i3, pred, succ, pdest, psrc) rtx insn; rtx i3; rtx pred, succ; rtx *pdest, *psrc;{ int i; rtx set = 0, src, dest; rtx p, link; int all_adjacent = (succ ? (next_active_insn (insn) == succ && next_active_insn (succ) == i3) : next_active_insn (insn) == i3); /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0. or a PARALLEL consisting of such a SET and CLOBBERs. If INSN has CLOBBER parallel parts, ignore them for our processing. By definition, these happen during the execution of the insn. When it is merged with another insn, all bets are off. If they are, in fact, needed and aren't also supplied in I3, they may be added by recog_for_combine. Otherwise, it won't match. We can also ignore a SET whose SET_DEST is mentioned in a REG_UNUSED note. Get the source and destination of INSN. If more than one, can't combine. */ if (GET_CODE (PATTERN (insn)) == SET) set = PATTERN (insn); else if (GET_CODE (PATTERN (insn)) == PARALLEL && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET) { for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) { rtx elt = XVECEXP (PATTERN (insn), 0, i); switch (GET_CODE (elt)) { /* We can ignore CLOBBERs. */ case CLOBBER: break; case SET: /* Ignore SETs whose result isn't used but not those that have side-effects. */ if (find_reg_note (insn, REG_UNUSED, SET_DEST (elt)) && ! side_effects_p (elt)) break; /* If we have already found a SET, this is a second one and so we cannot combine with this insn. */ if (set) return 0; set = elt; break; default: /* Anything else means we can't combine. */ return 0; } } if (set == 0 /* If SET_SRC is an ASM_OPERANDS we can't throw away these CLOBBERs, so don't do anything with it. */ || GET_CODE (SET_SRC (set)) == ASM_OPERANDS) return 0; } else return 0; if (set == 0) return 0; set = expand_field_assignment (set); src = SET_SRC (set), dest = SET_DEST (set); /* Don't eliminate a store in the stack pointer. */ if (dest == stack_pointer_rtx /* 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 eliminate a function call argument. */ || (GET_CODE (i3) == CALL_INSN && (find_reg_fusage (i3, USE, dest) || (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER && global_regs[REGNO (dest)]))) /* 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). If INSN has a REG_EQUIV note, the register is always equivalent to the memory so the substitution is valid even if there are intervening stores. Also, don't move a volatile asm or UNSPEC_VOLATILE across any other insns. */ || (! all_adjacent && (((GET_CODE (src) != MEM || ! find_reg_note (insn, REG_EQUIV, src)) && use_crosses_set_p (src, INSN_CUID (insn))) || (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src)) || GET_CODE (src) == UNSPEC_VOLATILE)) /* 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. This is the same test done in can_combine except that we don't test if SRC is a CALL operation to permit a hard register with SMALL_REGISTER_CLASSES, and that we have to take all_adjacent into account. */ if (GET_CODE (src) == REG && ((REGNO (dest) < FIRST_PSEUDO_REGISTER && ! HARD_REGNO_MODE_OK (REGNO (dest), GET_MODE (dest))) /* Don't extend the life of a hard register unless it is user variable (if we have few registers) or it can't fit into the desired register (meaning something special is going on). Also avoid substituting a return register into I3, because reload can't handle a conflict with constraints of other inputs. */ || (REGNO (src) < FIRST_PSEUDO_REGISTER && (! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)) || (SMALL_REGISTER_CLASSES && ((! all_adjacent && ! REG_USERVAR_P (src)) || (FUNCTION_VALUE_REGNO_P (REGNO (src)) && ! REG_USERVAR_P (src)))))))) 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 there are any volatile insns between INSN and I3, reject, because they might affect machine state. */ for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p)) if (GET_RTX_CLASS (GET_CODE (p)) == 'i' && p != succ && volatile_insn_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;}/* Check if PAT is an insn - or a part of it - used to set up an argument for a function in a hard register. */static intsets_function_arg_p (pat) rtx pat;{ int i; rtx inner_dest; switch (GET_CODE (pat)) { case INSN: return sets_function_arg_p (PATTERN (pat)); case PARALLEL: for (i = XVECLEN (pat, 0); --i >= 0;) if (sets_function_arg_p (XVECEXP (pat, 0, i))) return 1; break; case SET: inner_dest = SET_DEST (pat); while (GET_CODE (inner_dest) == STRICT_LOW_PART || GET_CODE (inner_dest) == SUBREG || GET_CODE (inner_dest) == ZERO_EXTRACT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -