?? combine.c
字號:
now supposed to appear. */ if (((was_replaced[0] && GET_CODE (XEXP (x, 1)) == PLUS) || (was_replaced[1] && GET_CODE (XEXP (x, 0)) == PLUS)) || ((was_replaced[0] || was_replaced[1]) && GET_CODE (to) == PLUS)) { rtx offset = 0, base, index; if (GET_CODE (to) != PLUS) { index = to; base = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0); } else { index = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0); base = to; } if (CONSTANT_ADDRESS_P (XEXP (base, 0))) { offset = XEXP (base, 0); base = XEXP (base, 1); } else if (CONSTANT_ADDRESS_P (XEXP (base, 1))) { offset = XEXP (base, 1); base = XEXP (base, 0); } if (offset != 0) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); if (GET_CODE (offset) == CONST_INT) return plus_constant (gen_rtx (PLUS, GET_MODE (index), base, index), INTVAL (offset)); if (GET_CODE (index) == CONST_INT) return plus_constant (gen_rtx (PLUS, GET_MODE (offset), base, offset), INTVAL (index)); return gen_rtx (PLUS, GET_MODE (index), gen_rtx (PLUS, GET_MODE (index), base, index), offset); } } break; case EQ: case NE: /* If comparing a subreg against zero, discard the subreg. */ if (was_replaced[0] && GET_CODE (to) == SUBREG && SUBREG_WORD (to) == 0 && XEXP (x, 1) == const0_rtx) SUBST (XEXP (x, 0), SUBREG_REG (to)); /* If comparing a ZERO_EXTRACT against zero, canonicalize to a SIGN_EXTRACT, since the two are equivalent here. */ if (was_replaced[0] && GET_CODE (to) == ZERO_EXTRACT && XEXP (x, 1) == const0_rtx) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); SUBST (XEXP (x, 0), gen_rtx (SIGN_EXTRACT, GET_MODE (to), XEXP (to, 0), XEXP (to, 1), XEXP (to, 2))); }#ifndef BITS_BIG_ENDIAN /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0), arrange to return (EQ (SIGN_EXTRACT y 1 x) 0), which is what jump-on-bit instructions are written with. */ else if (XEXP (x, 1) == const0_rtx && GET_CODE (XEXP (x, 0)) == AND && (XEXP (XEXP (x, 0), 0) == to || XEXP (XEXP (x, 0), 1) == to) && GET_CODE (to) == ASHIFT && XEXP (to, 0) == const1_rtx) { register rtx y = XEXP (XEXP (x, 0), XEXP (XEXP (x, 0), 0) == to); if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); SUBST (XEXP (x, 0), gen_rtx (SIGN_EXTRACT, GET_MODE (to), y, const1_rtx, XEXP (to, 1))); }#endif /* not BITS_BIG_ENDIAN */ /* Negation is a no-op before equality test against zero. */ if (GET_CODE (XEXP (x, 0)) == NEG && XEXP (x, 1) == const0_rtx) { SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0)); } if (GET_CODE (XEXP (x, 1)) == NEG && XEXP (x, 0) == const0_rtx) { SUBST (XEXP (x, 1), XEXP (XEXP (x, 1), 0)); } break; case ZERO_EXTEND: /* Nested zero-extends are equivalent to just one. */ if (was_replaced[0] && GET_CODE (to) == ZERO_EXTEND) SUBST (XEXP (x, 0), XEXP (to, 0)); /* Zero extending a constant int can be replaced by a zero-extended constant. */ if (was_replaced[0] && HOST_BITS_PER_INT >= GET_MODE_BITSIZE (GET_MODE (from)) && GET_CODE (to) == CONST_INT) { int intval = INTVAL (to) & GET_MODE_MASK (GET_MODE (from)); if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (CONST_INT, VOIDmode, intval); } /* Zero-extending the result of an and with a constant can be done with a wider and. */ if (was_replaced[0] && GET_CODE (to) == AND && GET_CODE (XEXP (to, 1)) == CONST_INT && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)) /* Avoid getting wrong result if the constant has high bits set that are irrelevant in the narrow mode where it is being used. */ && 0 == (INTVAL (XEXP (to, 1)) & ~ GET_MODE_MASK (GET_MODE (to)))) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (AND, GET_MODE (x), gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), XEXP (to, 1)); } /* Change (zero_extend:M (subreg:N (zero_extract:M ...) 0)) to (zero_extract:M ...) if the field extracted fits in mode N. */ if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTRACT && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) <= GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))) { return XEXP (XEXP (x, 0), 0); } /* Change (zero_extend:M (subreg:N (and:M ... <const>) 0)) to (and:M ...) if the significant bits fit in mode N. */ if (GET_CODE (XEXP (x, 0)) == SUBREG && SUBREG_REG (XEXP (x, 0)) == to && SUBREG_WORD (XEXP (x, 0)) == 0 && GET_CODE (to) == AND && GET_CODE (XEXP (to, 1)) == CONST_INT && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)) /* Avoid getting wrong result if the constant has high bits set that are irrelevant in the narrow mode where it is being used. */ && 0 == (INTVAL (XEXP (to, 1)) & ~ GET_MODE_MASK (GET_MODE (to)))) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (AND, GET_MODE (x), gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), XEXP (to, 1)); } /* In (zero_extend:M (subreg:N (lshiftrt:M REG))), where REG was assigned from (zero_extend:M (any:N ...)), remove the outer zero extension. */ if (GET_CODE (XEXP (x, 0)) == SUBREG && SUBREG_REG (XEXP (x, 0)) == to && SUBREG_WORD (XEXP (x, 0)) == 0 && GET_CODE (to) == LSHIFTRT) { rtx tmp = XEXP (to, 0); /* See if arg of LSHIFTRT is a register whose value we can find. */ if (GET_CODE (tmp) == REG) if (reg_n_sets[REGNO (tmp)] == 1 && reg_last_set[REGNO (tmp)] != 0 && SET_DEST (PATTERN (reg_last_set[REGNO (tmp)])) == tmp) tmp = SET_SRC (PATTERN (reg_last_set[REGNO (tmp)])); else break; if (GET_CODE (tmp) == ZERO_EXTEND && GET_MODE (tmp) == GET_MODE (x) && GET_MODE (XEXP (tmp, 0)) == GET_MODE (XEXP (x, 0))) return SUBREG_REG (XEXP (x, 0)); } break; case SIGN_EXTEND: /* Nested sign-extends are equivalent to just one. */ if (was_replaced[0] && GET_CODE (to) == SIGN_EXTEND) SUBST (XEXP (x, 0), XEXP (to, 0)); /* Sign extending a constant int can be replaced by a sign-extended constant. */ if (was_replaced[0] && HOST_BITS_PER_INT >= GET_MODE_BITSIZE (GET_MODE (from)) && GET_CODE (to) == CONST_INT) { int intval = INTVAL (to); if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); if (intval > 0 && (intval & (1 << (GET_MODE_BITSIZE (GET_MODE (from)) - 1)))) intval |= ~ GET_MODE_MASK (GET_MODE (from)); return gen_rtx (CONST_INT, VOIDmode, intval); } /* Sign-extending the result of an and with a constant can be done with a wider and, provided the high bit of the constant is 0. */ if (was_replaced[0] && GET_CODE (to) == AND && GET_CODE (XEXP (to, 1)) == CONST_INT && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)) && ((INTVAL (XEXP (to, 1)) & (-1 << (GET_MODE_BITSIZE (GET_MODE (to)) - 1))) == 0)) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (AND, GET_MODE (x), gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), XEXP (to, 1)); } /* hacks added by tiemann. */ /* Change (sign_extend:M (subreg:N (and:M ... <const>) 0)) to (and:M ...), provided the result fits in mode N, and the high bit of the constant is 0 in mode N. */ if (GET_CODE (XEXP (x, 0)) == SUBREG && SUBREG_REG (XEXP (x, 0)) == to && SUBREG_WORD (XEXP (x, 0)) == 0 && GET_CODE (to) == AND && GET_CODE (XEXP (to, 1)) == CONST_INT && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)) && ((INTVAL (XEXP (to, 1)) & (-1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))) == 0)) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (AND, GET_MODE (x), gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), XEXP (to, 1)); } /* In (sign_extend:M (subreg:N (ashiftrt:M REG))), where REG was assigned from (sign_extend:M (any:N ...)), remove the outer sign extension. */ if (GET_CODE (XEXP (x, 0)) == SUBREG && SUBREG_REG (XEXP (x, 0)) == to && SUBREG_WORD (XEXP (x, 0)) == 0 && GET_CODE (to) == ASHIFTRT) { rtx tmp = XEXP (to, 0); /* See if arg of LSHIFTRT is a register whose value we can find. */ if (GET_CODE (tmp) == REG) if (reg_n_sets[REGNO (tmp)] == 1 && reg_last_set[REGNO (tmp)] != 0 && SET_DEST (PATTERN (reg_last_set[REGNO (tmp)])) == tmp) tmp = SET_SRC (PATTERN (reg_last_set[REGNO (tmp)])); else break; if (GET_CODE (tmp) == SIGN_EXTEND && GET_MODE (tmp) == GET_MODE (x) && GET_MODE (XEXP (tmp, 0)) == GET_MODE (XEXP (x, 0))) return SUBREG_REG (XEXP (x, 0)); } break; case SET: /* In (set (zero-extract <x> <n> <y>) (and <foo> <(2**n-1) | anything>)) the `and' can be deleted. This can happen when storing a bit that came from a set-flag insn followed by masking to one bit. */ if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && was_replaced[1] && GET_CODE (to) == AND && GET_CODE (XEXP (to, 1)) == CONST_INT && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1) & ~ INTVAL (XEXP (to, 1)))) { SUBST (XEXP (x, 1), XEXP (to, 0)); } /* In (set (zero-extract <x> <n> <y>) (subreg (and <foo> <(2**n-1) | anything>))) the `and' can be deleted. */ if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && GET_CODE (XEXP (x, 1)) == SUBREG && SUBREG_WORD (XEXP (x, 1)) == 0 && GET_CODE (SUBREG_REG (XEXP (x, 1))) == AND && GET_CODE (XEXP (SUBREG_REG (XEXP (x, 1)), 1)) == CONST_INT && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1) & ~ INTVAL (XEXP (SUBREG_REG (XEXP (x, 1)), 1)))) { SUBST (SUBREG_REG (XEXP (x, 1)), XEXP (SUBREG_REG (XEXP (x, 1)), 0)); } /* (set (zero_extract ...) (and/or/xor (zero_extract ...) const)), if both zero_extracts have the same location, size and position, can be changed to avoid the byte extracts. */ if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT || GET_CODE (XEXP (x, 0)) == SIGN_EXTRACT) && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && (GET_CODE (XEXP (x, 1)) == AND || GET_CODE (XEXP (x, 1)) == IOR || GET_CODE (XEXP (x, 1)) == XOR) && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)) && GET_CODE (XEXP (XEXP (x, 1), 0)) == GET_CODE (XEXP (x, 0)) && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT /* zero_extract can apply to a QImode even if the bits extracted don't fit inside that byte. In such a case, we may not do this optimization, since the OR or AND insn really would need to fit in a byte. */ && (INTVAL (XEXP (XEXP (x, 0), 1)) + INTVAL (XEXP (XEXP (x, 0), 2)) < GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0))))) { int shiftcount; int fieldsize; int newmask;#ifdef BITS_BIG_ENDIAN shiftcount = GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0))) - INTVAL (XEXP (XEXP (x, 0), 1)) - INTVAL (XEXP (XEXP (x, 0), 2));#else shiftcount = INTVAL (XEXP (XEXP (x, 0), 2));#endif fieldsize = INTVAL (XEXP (XEXP (x, 0), 1)); newmask = ((INTVAL (XEXP (XEXP (x, 1), 1)) << shiftcount) + (GET_CODE (XEXP (x, 1)) == AND /* For AND, preserve the bits outside this field. */ ? ((1 << shiftcount) - 1 + (-1 << (shiftcount + fieldsize))) : 0)); if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0))) < HOST_BITS_PER_INT) newmask &= (1 << GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))) - 1; if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (SET, VOIDmode, XEXP (XEXP (x, 0), 0), gen_rtx (GET_CODE (XEXP (x, 1)), GET_MODE (XEXP (XEXP (x, 0), 0)), XEXP (XEXP (XEXP (x, 1), 0), 0), gen_rtx (CONST_INT, VOIDmode, newmask))); } /* Can simplify (set (cc0) (compare (zero/sign_extend FOO) CONST)) to (set (cc0) (compare FOO CONST)) if CONST fits in FOO's mode and we are only testing equality. In fact, this is valid for zero_extend if what follows is an unsigned comparison, and for sign_extend with a signed comparison. */ if (SET_DEST (x) == cc0_rtx && GET_CODE (SET_SRC (x)) == COMPARE && (GET_CODE (XEXP (SET_SRC (x), 0)) == ZERO_EXTEND || GET_CODE (XEXP (SET_SRC (x), 0)) == SIGN_EXTEND) && next_insn_tests_no_inequality (subst_insn) && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT /* This is overly cautious by one bit, but saves worrying about whether it is zero-extension or sign extension. */ && ((unsigned) INTVAL (XEXP (SET_SRC (x), 1)) < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (SET_SRC (x), 0), 0))) - 1)))) SUBST (XEXP (SET_SRC (x), 0), XEXP (XEXP (SET_SRC (x), 0), 0)); break; case AND: if (GET_CODE (XEXP (x, 1)) == CONST_INT) { rtx tem = simplify_and_const_int (x, to); if (tem) return tem; } break; case IOR: case XOR: /* (ior (ior x c1) c2) => (ior x c1|c2); likewise for xor. */ if (GET_CODE (XEXP (x, 1)) == CONST_INT && GET_CODE (XEXP (x, 0)) == code
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -