📄 cse.c
字号:
const_arg2 = 0; /* Try folding our operands. Then see which ones have constant values known. */ fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') { register rtx tem = fold_rtx (XEXP (x, i), copyflag); /* If an operand has changed under folding, and we are not supposed to alter the original structure, copy X if we haven't yet done so. */ if (! copied && tem != XEXP (x, i)) { int j; rtx new = rtx_alloc (code); PUT_MODE (new, GET_MODE (x)); for (j = 0; j < GET_RTX_LENGTH (code); j++) XINT (new, j) = XINT (x, j); x = new; copied = 1; } /* Install the possibly altered folded operand. */ XEXP (x, i) = tem; /* For the first three operands, see if the operand is constant or equivalent to a constant. */ if (i < 3) { rtx const_arg = equiv_constant (tem); switch (i) { case 0: const_arg0 = const_arg; break; case 1: const_arg1 = const_arg; break; case 2: const_arg2 = const_arg; break; } } } else if (fmt[i] == 'E') /* Don't try to fold inside of a vector of expressions. Doing nothing is is harmless. */ ; /* If a commutative operation, place a constant integer as the second operand unless the first operand is also a constant integer. Otherwise, place any constant second unless the first operand is also a constant. */ switch (code) { case PLUS: case MULT: case UMULT: case AND: case IOR: case XOR: case NE: case EQ: if (const_arg0 && const_arg0 == XEXP (x, 0) && (! (const_arg1 && const_arg1 == XEXP (x, 1)) || (GET_CODE (const_arg0) == CONST_INT && GET_CODE (const_arg1) != CONST_INT))) { register rtx tem; if (! copied) copied = 1, x = copy_rtx (x); tem = XEXP (x, 0); XEXP (x, 0) = XEXP (x, 1); XEXP (x, 1) = tem; tem = const_arg0; const_arg0 = const_arg1; const_arg1 = tem; } break; } /* Now decode the kind of rtx X is and then return X (if nothing can be done) or return a folded rtx or store a value in VAL and drop through (to return a CONST_INT for the integer VAL). */ if (GET_RTX_LENGTH (code) == 1) { if (const_arg0 == 0) return x; if (GET_CODE (const_arg0) == CONST_INT) { register int arg0 = INTVAL (const_arg0); switch (GET_CODE (x)) { case NOT: val = ~ arg0; break; case NEG: val = - arg0; break; case TRUNCATE: val = arg0; break; case ZERO_EXTEND: { enum machine_mode mode = GET_MODE (XEXP (x, 0)); if (mode == VOIDmode) return x; if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) val = arg0 & ~((-1) << GET_MODE_BITSIZE (mode)); else return x; break; } case SIGN_EXTEND: { enum machine_mode mode = GET_MODE (XEXP (x, 0)); if (mode == VOIDmode) return x; if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) { val = arg0 & ~((-1) << GET_MODE_BITSIZE (mode)); if (val & (1 << (GET_MODE_BITSIZE (mode) - 1))) val -= 1 << GET_MODE_BITSIZE (mode); } else return x; break; } default: return x; } }#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) else if (GET_CODE (const_arg0) == CONST_DOUBLE && GET_CODE (x) == NEG && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) { union real_extract u; register REAL_VALUE_TYPE arg0; jmp_buf handler; if (setjmp (handler)) { warning ("floating point trap in constant folding"); return x; } set_float_handler (handler); bcopy (&CONST_DOUBLE_LOW (const_arg0), &u, sizeof u); arg0 = u.d; u.d = REAL_VALUE_NEGATE (arg0); x = immed_real_const_1 (u.d, GET_MODE (x)); set_float_handler (0); return x; }#endif else return x; } else if (GET_RTX_LENGTH (code) == 2) { register int arg0, arg1, arg0s, arg1s; int arithwidth = width; /* If 1st arg is the condition codes, 2nd must be zero and this must be a comparison. Decode the info on how the previous insn set the cc0 and use that to deduce result of comparison. */ if (XEXP (x, 0) == cc0_rtx || GET_CODE (XEXP (x, 0)) == COMPARE) { if (XEXP (x, 0) == cc0_rtx) arg0 = prev_insn_cc0; else arg0 = fold_cc0 (VOIDmode, XEXP (x, 0)); if (arg0 == 0 || const_arg1 != const0_rtx /* 0200 bit in arg0 means only zeroness is known, and sign is not known. */ || ((arg0 & 0200) != 0 && code != EQ && code != NE)) return x; /* Extract either the signed or the unsigned digit from ARG0. */ if (code == LEU || code == LTU || code == GEU || code == GTU) arg0 = arg0 & 7; else arg0 = (arg0 >> 3) & 7; if (arg0 == 7) arg0 = -1; switch (code) { case LE: case LEU: return (arg0 <= 0) ? const1_rtx : const0_rtx; case LT: case LTU: return (arg0 < 0) ? const1_rtx : const0_rtx; case GE: case GEU: return (arg0 >= 0) ? const1_rtx : const0_rtx; case GT: case GTU: return (arg0 > 0) ? const1_rtx : const0_rtx; case NE: return (arg0 != 0) ? const1_rtx : const0_rtx; case EQ: return (arg0 == 0) ? const1_rtx : const0_rtx; default: abort (); } } if (const_arg0 == 0 || const_arg1 == 0 || GET_CODE (const_arg0) != CONST_INT || GET_CODE (const_arg1) != CONST_INT) { /* Even if we can't compute a constant result, there are some cases worth simplifying. */ /* Note that we cannot rely on constant args to come last, even for commutative operators, because that happens only when the constant is explicit. */ switch (code) { case PLUS: if (const_arg0 == const0_rtx || const_arg0 == fconst0_rtx || const_arg0 == dconst0_rtx) return XEXP (x, 1); if (const_arg1 == const0_rtx || const_arg1 == fconst0_rtx || const_arg1 == dconst0_rtx) return XEXP (x, 0); /* Handle both-operands-constant cases. */ if (const_arg0 != 0 && const_arg1 != 0 && GET_CODE (const_arg0) != CONST_DOUBLE && GET_CODE (const_arg1) != CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) { if (GET_CODE (const_arg1) == CONST_INT) new = plus_constant (const_arg0, INTVAL (const_arg1));#if 0 /* Don't combine two constants if neither is an explicit integer. Assemblers can't handle the sum of two symbols. */ else { new = gen_rtx (PLUS, GET_MODE (x), const0_rtx, const0_rtx); XEXP (new, 0) = const_arg0; if (GET_CODE (const_arg0) == CONST) XEXP (new, 0) = XEXP (const_arg0, 0); XEXP (new, 1) = const_arg1; if (GET_CODE (const_arg1) == CONST) XEXP (new, 1) = XEXP (const_arg1, 0); new = gen_rtx (CONST, GET_MODE (new), new); }#endif /* 0 */ } else if (const_arg1 != 0 && GET_CODE (const_arg1) == CONST_INT && GET_CODE (XEXP (x, 0)) == PLUS && (CONSTANT_P (XEXP (XEXP (x, 0), 0)) || CONSTANT_P (XEXP (XEXP (x, 0), 1)))) /* constant + (variable + constant) can result if an index register is made constant. We simplify this by adding the constants. If we did not, it would become an invalid address. */ new = plus_constant (XEXP (x, 0), INTVAL (const_arg1)); break; case COMPARE: if (const_arg1 == const0_rtx) return XEXP (x, 0); if (XEXP (x, 0) == XEXP (x, 1) || (const_arg0 != 0 && const_arg0 == const_arg1)) { /* We can't assume x-x is 0 with IEEE floating point. */ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) return const0_rtx; } break; case MINUS: if (const_arg1 == const0_rtx || const_arg1 == fconst0_rtx || const_arg1 == dconst0_rtx) return XEXP (x, 0); if (XEXP (x, 0) == XEXP (x, 1) || (const_arg0 != 0 && const_arg0 == const_arg1)) { /* We can't assume x-x is 0 with IEEE floating point. */ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) return const0_rtx; } /* Change subtraction from zero into negation. */ if (const_arg0 == const0_rtx) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 1)); /* Don't let a relocatable value get a negative coeff. */ if (const_arg0 != 0 && const_arg1 != 0 && GET_CODE (const_arg1) == CONST_INT) new = plus_constant (const_arg0, - INTVAL (const_arg1)); break; case MULT: case UMULT: if (const_arg1 && GET_CODE (const_arg1) == CONST_INT && INTVAL (const_arg1) == -1 /* Don't do this in the case of widening multiplication. */ && GET_MODE (XEXP (x, 0)) == GET_MODE (x)) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 0)); if (const_arg0 && GET_CODE (const_arg0) == CONST_INT && INTVAL (const_arg0) == -1 && GET_MODE (XEXP (x, 1)) == GET_MODE (x)) return gen_rtx (NEG, GET_MODE (x), XEXP (x, 1)); if (const_arg1 == const0_rtx || const_arg0 == const0_rtx) new = const0_rtx; if (const_arg1 == fconst0_rtx || const_arg0 == fconst0_rtx) new = fconst0_rtx; if (const_arg1 == dconst0_rtx || const_arg0 == dconst0_rtx) new = dconst0_rtx; if (const_arg1 == const1_rtx) return XEXP (x, 0); if (const_arg0 == const1_rtx) return XEXP (x, 1); break; case IOR: if (const_arg1 == const0_rtx) return XEXP (x, 0); if (const_arg0 == const0_rtx) return XEXP (x, 1); if (const_arg1 && GET_CODE (const_arg1) == CONST_INT && (INTVAL (const_arg1) & GET_MODE_MASK (GET_MODE (x))) == GET_MODE_MASK (GET_MODE (x))) new = const_arg1; if (const_arg0 && GET_CODE (const_arg0) == CONST_INT && (INTVAL (const_arg0) & GET_MODE_MASK (GET_MODE (x))) == GET_MODE_MASK (GET_MODE (x))) new = const_arg0; break; case XOR: if (const_arg1 == const0_rtx) return XEXP (x, 0); if (const_arg0 == const0_rtx) return XEXP (x, 1); if (const_arg1 && GET_CODE (const_arg1) == CONST_INT && (INTVAL (const_arg1) & GET_MODE_MASK (GET_MODE (x))) == GET_MODE_MASK (GET_MODE (x))) return gen_rtx (NOT, GET_MODE (x), XEXP (x, 0)); if (const_arg0 && GET_CODE (const_arg0) == CONST_INT && (INTVAL (const_arg0) & GET_MODE_MASK (GET_MODE (x))) == GET_MODE_MASK (GET_MODE (x))) return gen_rtx (NOT, GET_MODE (x), XEXP (x, 1)); break; case AND: if (const_arg1 == const0_rtx || const_arg0 == const0_rtx) new = const0_rtx; if (const_arg1 && GET_CODE (const_arg1) == CONST_INT && (INTVAL (const_arg1) & GET_MODE_MASK (GET_MODE (x))) == GET_MODE_MASK (GET_MODE (x))) return XEXP (x, 0); if (const_arg0 && GET_CODE (const_arg0) == CONST_INT && (INTVAL (const_arg0) & GET_MODE_MASK (GET_MODE (x))) == GET_MODE_MASK (GET_MODE (x))) return XEXP (x, 1); break; case DIV: case UDIV: if (const_arg1 == const1_rtx) return XEXP (x, 0); if (const_arg0 == const0_rtx) new = const0_rtx; break; case UMOD: case MOD: if (const_arg0 == const0_rtx || const_arg1 == const1_rtx) new = const0_rtx; break; case LSHIFT: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT: case ROTATERT: if (const_arg1 == const0_rtx) return XEXP (x, 0); if (const_arg0 == const0_rtx) new = const_arg0; break; } if (new != 0 && LEGITIMATE_CONSTANT_P (new)) return new; return x; } if (arithwidth == 0) { if (GET_MODE (XEXP (x, 0)) != VOIDmode) arithwidth = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))); if (GET_MODE (XEXP (x, 1)) != VOIDmode) arithwidth = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 1))); } /* Get the integer argument values in two forms: zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S. */ arg0 = INTVAL (const_arg0); arg1 = INTVAL (const_arg1); if (arithwidth < HOST_BITS_PER_INT && arithwidth > 0) { arg0 &= (1 << arithwidth) - 1; arg1 &= (1 << arithwidth) - 1; arg0s = arg0; if (arg0s & (1 << (arithwidth - 1))) arg0s |= ((-1) << arithwidth); arg1s = arg1; if (arg1s & (1 << (arithwidth - 1))) arg1s |= ((-1) << arithwidth); } else { arg0s = arg0; arg1s = arg1; } /* Compute the value of the arithmetic. */ switch (code) { case PLUS: val = arg0 + arg1; break; case MINUS: val = arg0 - arg1; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -