?? combine.c
字號:
} add_incs (i3, REG_NOTES (i1)); LOG_LINKS (i1) = 0; PUT_CODE (i1, NOTE); NOTE_LINE_NUMBER (i1) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (i1) = 0; } /* Get rid of I2. */ LOG_LINKS (i2) = 0; PUT_CODE (i2, NOTE); NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (i2) = 0; combine_successes++; return 1; } /* Failure: change I3 back the way it was. */ undo_all (); return 0;}/* Undo all the modifications recorded in undobuf. */static voidundo_all (){ register int i; if (undobuf.num_undo > MAX_UNDO) undobuf.num_undo = MAX_UNDO; for (i = undobuf.num_undo - 1; i >= 0; i--) *undobuf.undo[i].where = undobuf.undo[i].old_contents; if (undobuf.storage) obfree (undobuf.storage); undobuf.num_undo = 0; undobuf.storage = 0;}/* If this insn had more than one substitution, copy all but one, so that no invalid shared substructure is introduced. */static voidcopy_substitutions (){ register int i; if (undobuf.num_undo > 1) { for (i = undobuf.num_undo - 1; i >= 1; i--) if (! undobuf.undo[i].is_int) *undobuf.undo[i].where = copy_rtx (*undobuf.undo[i].where); }}/* Throughout X, replace FROM with TO, and return the result. The result is TO if X is FROM; otherwise the result is X, but its contents may have been modified. If they were modified, a record was made in undobuf so that undo_all will (among other things) return X to its original state. If the number of changes necessary is too much to record to undo, the excess changes are not made, so the result is invalid. The changes already made can still be undone. undobuf.num_undo is incremented for such changes, so by testing that the caller can tell whether the result is valid. `n_occurrences' is incremented each time FROM is replaced. */static rtxsubst (x, from, to) register rtx x, from, to;{ register char *fmt; register int len, i; register enum rtx_code code; char was_replaced[2];#define SUBST(INTO, NEWVAL) \ do { if (undobuf.num_undo < MAX_UNDO) \ { \ undobuf.undo[undobuf.num_undo].where = &INTO; \ undobuf.undo[undobuf.num_undo].old_contents = INTO; \ undobuf.undo[undobuf.num_undo].is_int = 0; \ INTO = NEWVAL; \ } \ undobuf.num_undo++; } while (0)#define SUBST_INT(INTO, NEWVAL) \ do { if (undobuf.num_undo < MAX_UNDO) \ { \ struct undo_int *u = (struct undo_int *)&undobuf.undo[undobuf.num_undo];\ u->where = &INTO; \ u->old_contents = INTO; \ u->is_int = 1; \ INTO = NEWVAL; \ } \ undobuf.num_undo++; } while (0)/* FAKE_EXTEND_SAFE_P (MODE, FROM) is 1 if (subreg:MODE FROM 0) is a safe replacement for (zero_extend:MODE FROM) or (sign_extend:MODE FROM). If it is 0, that cannot be done. We can now do this for any MEM because (SUBREG (MEM...)) is guaranteed to cause the MEM to be reloaded. If not for that, MEM's would very rarely be safe. *//* Reject MODEs bigger than a word, because we might not be able to reference a two-register group starting with an arbitrary register (and currently gen_lowpart might crash for a SUBREG). */#define FAKE_EXTEND_SAFE_P(MODE, FROM) \ (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ && (GET_CODE (FROM) == REG || GET_CODE (FROM) == SUBREG \ || GET_CODE (FROM) == MEM)) if (x == from) return to; /* It is possible to have a subexpression appear twice in the insn. Suppose that FROM is a register that appears within TO. Then, after that subexpression has been scanned once by `subst', the second time it is scanned, TO may be found. If we were to scan TO here, we would find FROM within it and create a self-referent rtl structure which is completely wrong. */ if (x == to) return to; code = GET_CODE (x); /* A little bit of algebraic simplification here. */ switch (code) { /* This case has no effect except to speed things up. */ case REG: case CONST_INT: case CONST: case SYMBOL_REF: case LABEL_REF: case PC: case CC0: return x; } was_replaced[0] = 0; was_replaced[1] = 0; len = GET_RTX_LENGTH (code); fmt = GET_RTX_FORMAT (code); /* Don't replace FROM where it is being stored in rather than used. */ if (code == SET && SET_DEST (x) == from) fmt = "ie"; if (code == SET && GET_CODE (SET_DEST (x)) == SUBREG && SUBREG_REG (SET_DEST (x)) == from) fmt = "ie"; for (i = 0; i < len; i++) { if (fmt[i] == 'E') { register int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) { register rtx new; if (XVECEXP (x, i, j) == from) new = to, n_occurrences++; else new = subst (XVECEXP (x, i, j), from, to); if (new != XVECEXP (x, i, j)) SUBST (XVECEXP (x, i, j), new); } } else if (fmt[i] == 'e') { register rtx new; if (XEXP (x, i) == from) { new = to; n_occurrences++; if (i < 2) was_replaced[i] = 1; } else new = subst (XEXP (x, i), from, to); if (new != XEXP (x, i)) SUBST (XEXP (x, i), new); } } /* A little bit of algebraic simplification here. */ switch (code) { case SUBREG: /* Changing mode twice with SUBREG => just change it once, or not at all if changing back to starting mode. */ if (SUBREG_REG (x) == to && GET_CODE (to) == SUBREG) { if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))) if (SUBREG_WORD (x) == 0 && SUBREG_WORD (to) == 0) return SUBREG_REG (to); SUBST (SUBREG_REG (x), SUBREG_REG (to)); if (SUBREG_WORD (to) != 0) SUBST_INT (SUBREG_WORD (x), SUBREG_WORD (x) + SUBREG_WORD (to)); } if (SUBREG_REG (x) == to && (GET_CODE (to) == SIGN_EXTEND || GET_CODE (to) == ZERO_EXTEND) && subreg_lowpart_p (x)) { /* (subreg (sign_extend X)) is X, if it has same mode as X. */ if (GET_MODE (x) == GET_MODE (XEXP (to, 0))) return XEXP (to, 0); /* (subreg (sign_extend X)), if it has a mode wider than X, can be done with (sign_extend X). */ if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (GET_CODE (to), GET_MODE (x), XEXP (to, 0)); } /* Extend and then truncate smaller than it was to start with: no need to extend. */ if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))) { SUBST (XEXP (x, 0), XEXP (to, 0)); } } /* (subreg:A (mem:B X) N) becomes a modified MEM. If we can't do that safely, then it becomes something nonsensical so that this combination won't take place. This avoids producing any (subreg (mem))s except in the special paradoxical case where gen_lowpart_for_combine makes them. */ if (SUBREG_REG (x) == to && GET_CODE (to) == MEM) { int endian_offset = 0; /* Don't combine this if mode A is wider than B. */ if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (to))) return gen_rtx (CLOBBER, VOIDmode, const0_rtx); /* Don't change the mode of the MEM if that would change the meaning of the address. */ if (mode_dependent_address_p (XEXP (to, 0))) return gen_rtx (CLOBBER, VOIDmode, const0_rtx);#ifdef BYTES_BIG_ENDIAN if (GET_MODE_SIZE (GET_MODE (x)) < UNITS_PER_WORD) endian_offset += UNITS_PER_WORD - GET_MODE_SIZE (GET_MODE (x)); if (GET_MODE_SIZE (GET_MODE (to)) < UNITS_PER_WORD) endian_offset -= UNITS_PER_WORD - GET_MODE_SIZE (GET_MODE (to));#endif if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); /* Note if the plus_constant doesn't make a valid address then this combination won't be accepted. */ return gen_rtx (MEM, GET_MODE (x), plus_constant (XEXP (to, 0), (SUBREG_WORD (x) * UNITS_PER_WORD + endian_offset))); } break; case NOT: /* (not (minus X 1)) can become (neg X). */ if (was_replaced[0] && ((GET_CODE (to) == PLUS && INTVAL (XEXP (to, 1)) == -1) || (GET_CODE (to) == MINUS && XEXP (to, 1) == const1_rtx))) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (NEG, GET_MODE (to), XEXP (to, 0)); } /* Don't let substitution introduce double-negatives. */ if (was_replaced[0] && GET_CODE (to) == code) return XEXP (to, 0); break; case NEG: /* (neg (minus X Y)) can become (minus Y X). */ if (was_replaced[0] && GET_CODE (to) == MINUS) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (MINUS, GET_MODE (to), XEXP (to, 1), XEXP (to, 0)); } /* Don't let substitution introduce double-negatives. */ if (was_replaced[0] && GET_CODE (to) == code) return XEXP (to, 0); break; case FLOAT_TRUNCATE: /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF. */ if (was_replaced[0] && GET_CODE (to) == FLOAT_EXTEND && GET_MODE (XEXP (to, 0)) == GET_MODE (x)) return XEXP (to, 0); break;#if 0 case COMPARE: /* -x>0 if 0>x. */ if (GET_CODE (XEXP (x, 0)) == NEG && XEXP (x, 1) == const0_rtx) { SUBST (XEXP (x, 1), XEXP (XEXP (x, 0), 0)); SUBST (XEXP (x, 0), const0_rtx); } if (GET_CODE (XEXP (x, 1)) == NEG && XEXP (x, 0) == const0_rtx) { SUBST (XEXP (x, 0), XEXP (XEXP (x, 1), 0)); SUBST (XEXP (x, 1), const0_rtx); } break;#endif case PLUS:#if 0 /* Turned off for caution: turn it on after 1.36. */ /* Identify constant sums as such. */ if ((was_replaced[0] || was_replaced[1]) && CONSTANT_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1))) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (CONST, GET_MODE (x), x); }#endif /* In (plus <foo> (ashift <bar> <n>)) change the shift to a multiply so we can recognize scaled indexed addresses. */ if ((was_replaced[0] || was_replaced[1]) && GET_CODE (to) == ASHIFT && GET_CODE (XEXP (to, 1)) == CONST_INT && INTVAL (XEXP (to, 1)) < HOST_BITS_PER_INT) { rtx temp; if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); temp = gen_rtx (MULT, GET_MODE (to), XEXP (to, 0), gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (XEXP (to, 1)))); if (was_replaced[0]) SUBST (XEXP (x, 0), temp); else SUBST (XEXP (x, 1), temp); } /* (plus X (neg Y)) becomes (minus X Y). */ if (GET_CODE (XEXP (x, 1)) == NEG) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (MINUS, GET_MODE (x), XEXP (x, 0), XEXP (XEXP (x, 1), 0)); } /* (plus (neg X) Y) becomes (minus Y X). */ if (GET_CODE (XEXP (x, 0)) == NEG) { if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); return gen_rtx (MINUS, GET_MODE (x), XEXP (x, 1), XEXP (XEXP (x, 0), 0)); } /* (plus (plus x c1) c2) => (plus x c1+c2) */ if (GET_CODE (XEXP (x, 1)) == CONST_INT && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) { int sum = (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (XEXP (x, 0), 1))); if (sum == 0) return XEXP (XEXP (x, 0), 0); if (!undobuf.storage) undobuf.storage = (char *) oballoc (0); SUBST (XEXP (x, 1), gen_rtx (CONST_INT, VOIDmode, sum)); SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0)); break; } /* If we have something (putative index) being added to a sum, associate it so that any constant term is outermost. That's because that's the way indexed addresses are
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -