📄 fold-const.c
字号:
{ if (TREE_CODE (arg0) == INTEGER_CST) t = build_int_2 (~ TREE_INT_CST_LOW (arg0), ~ TREE_INT_CST_HIGH (arg0)); TREE_TYPE (t) = type; force_fit_type (t); } return t; case PLUS_EXPR: if (integer_zerop (arg0)) return convert (type, arg1); if (integer_zerop (arg1)) return convert (type, arg0); associate: /* In most languages, can't associate operations on floats through parentheses. Rather than remember where the parentheses were, we don't associate floats at all. It shouldn't matter much. */ if (TREE_CODE (type) == REAL_TYPE) goto binary; /* The varsign == -1 cases happen only for addition and subtraction. It says that the arg that was split was really CON minus VAR. The rest of the code applies to all associative operations. */ if (!wins) { tree var, con, tem; int varsign; if (split_tree (arg0, code, &var, &con, &varsign)) { if (varsign == -1) { /* EXPR is (CON-VAR) +- ARG1. */ /* If it is + and VAR==ARG1, return just CONST. */ if (code == PLUS_EXPR && operand_equal_p (var, arg1)) return convert (TREE_TYPE (t), con); /* Otherwise return (CON +- ARG1) - VAR. */ TREE_SET_CODE (t, MINUS_EXPR); TREE_OPERAND (t, 1) = var; TREE_OPERAND (t, 0) = fold (build (code, TREE_TYPE (t), con, arg1)); } else { /* EXPR is (VAR+CON) +- ARG1. */ /* If it is - and VAR==ARG1, return just CONST. */ if (code == MINUS_EXPR && operand_equal_p (var, arg1)) return convert (TREE_TYPE (t), con); /* Otherwise return VAR +- (ARG1 +- CON). */ TREE_OPERAND (t, 1) = tem = fold (build (code, TREE_TYPE (t), arg1, con)); TREE_OPERAND (t, 0) = var; if (integer_zerop (tem) && (code == PLUS_EXPR || code == MINUS_EXPR)) return var; /* If we have x +/- (c - d) [c an explicit integer] change it to x -/+ (d - c) since if d is relocatable then the latter can be a single immediate insn and the former cannot. */ if (TREE_CODE (tem) == MINUS_EXPR && TREE_CODE (TREE_OPERAND (tem, 0)) == INTEGER_CST) { tree tem1 = TREE_OPERAND (tem, 1); TREE_OPERAND (tem, 1) = TREE_OPERAND (tem, 0); TREE_OPERAND (tem, 0) = tem1; TREE_SET_CODE (t, (code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR)); } } return t; } if (split_tree (arg1, code, &var, &con, &varsign)) { /* EXPR is ARG0 +- (CON +- VAR). */ if (varsign == -1) TREE_SET_CODE (t, (code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR)); if (TREE_CODE (t) == MINUS_EXPR && operand_equal_p (var, arg0)) { /* If VAR and ARG0 cancel, return just CON or -CON. */ if (code == PLUS_EXPR) return convert (TREE_TYPE (t), con); return fold (build (NEGATE_EXPR, TREE_TYPE (t), convert (TREE_TYPE (t), con))); } TREE_OPERAND (t, 0) = fold (build (code, TREE_TYPE (t), arg0, con)); TREE_OPERAND (t, 1) = var; if (integer_zerop (TREE_OPERAND (t, 0)) && TREE_CODE (t) == PLUS_EXPR) return convert (TREE_TYPE (t), var); return t; } } binary:#if defined (REAL_IS_NOT_DOUBLE) && ! defined (REAL_ARITHMETIC) if (TREE_CODE (arg1) == REAL_CST) return t;#endif /* REAL_IS_NOT_DOUBLE, and no REAL_ARITHMETIC */ { register tree t1 = NULL_TREE; if (wins) t1 = combine (code, arg0, arg1); if (t1 != NULL_TREE) return t1; return t; } case MINUS_EXPR: if (! wins && integer_zerop (arg0)) return build (NEGATE_EXPR, type, arg1); if (integer_zerop (arg1)) return convert (type, arg0); /* Fold &x - &x. This can happen from &x.foo - &x. */ if (operand_equal_p (arg0, arg1)) return convert (TREE_TYPE (t), integer_zero_node); goto associate; case MULT_EXPR: if (!loses && integer_zerop (arg0)) return convert (type, arg0); if (!loses && integer_zerop (arg1)) return convert (type, arg1); if (integer_onep (arg0)) return convert (type, arg1); if (integer_onep (arg1)) return convert (type, arg0); goto associate; case BIT_IOR_EXPR: if (!loses && integer_all_onesp (arg0)) return convert (type, arg0); if (!loses && integer_all_onesp (arg1)) return convert (type, arg1); case BIT_XOR_EXPR: if (integer_zerop (arg0)) return convert (type, arg1); if (integer_zerop (arg1)) return convert (type, arg0); goto associate; case BIT_AND_EXPR: if (integer_all_onesp (arg0)) return convert (type, arg1); if (integer_all_onesp (arg1)) return convert (type, arg0); if (!loses && integer_zerop (arg0)) return convert (type, arg0); if (!loses && integer_zerop (arg1)) return convert (type, arg1); /* Simplify ((int)c & 0x377) into (int)c, if c is unsigned char. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == NOP_EXPR && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))) { int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))); if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT && (~TREE_INT_CST_LOW (arg0) & ((1 << prec) - 1)) == 0) return build (NOP_EXPR, type, TREE_OPERAND (arg1, 0)); } if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0)))) { int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))); if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT && (~TREE_INT_CST_LOW (arg1) & ((1 << prec) - 1)) == 0) return build (NOP_EXPR, type, TREE_OPERAND (arg0, 0)); } goto associate; case BIT_ANDTC_EXPR: if (integer_all_onesp (arg0)) return convert (type, arg1); if (integer_zerop (arg1)) return convert (type, arg0); if (!loses && integer_zerop (arg0)) return convert (type, arg0); if (!loses && integer_all_onesp (arg1)) return combine (code, arg1, arg1); goto binary; case TRUNC_DIV_EXPR: case ROUND_DIV_EXPR: case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR: case EXACT_DIV_EXPR: case RDIV_EXPR: if (integer_onep (arg1)) return convert (type, arg0); if (integer_zerop (arg1)) return t;#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) if (TREE_CODE (arg1) == REAL_CST && real_zerop (arg1)) return t;#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ goto binary; case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: case TRUNC_MOD_EXPR: if (!loses && integer_onep (arg1)) return combine (code, arg1, arg1); if (integer_zerop (arg1)) return t; goto binary; case LSHIFT_EXPR: case RSHIFT_EXPR: case LROTATE_EXPR: case RROTATE_EXPR: if (integer_zerop (arg1)) return convert (type, arg0); goto binary; case MIN_EXPR: case MAX_EXPR: goto associate; case TRUTH_NOT_EXPR: /* Note that the operand of this must be an int and its values must be 0 or 1. ("true" is a fixed value perhaps depending on the language, but we don't handle values other than 1 correctly yet.) */ if (TREE_CODE (arg0) == INTEGER_CST) { t = build_int_2 ((TREE_INT_CST_LOW (arg0) == 0 && TREE_INT_CST_HIGH (arg0) == 0), 0); TREE_TYPE (t) = integer_type_node; } return t; case TRUTH_ANDIF_EXPR: /* Note that the operands of this must be ints and their values must be 0 or 1. ("true" is a fixed value perhaps depending on the language.) */ /* If first arg is constant zero, return it. */ if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0)) return arg0; case TRUTH_AND_EXPR: /* If either arg is constant true, drop it. */ if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0)) return arg1; if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)) return arg0; /* Both known to be zero => return zero. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) return arg0; return t; case TRUTH_ORIF_EXPR: /* Note that the operands of this must be ints and their values must be 0 or true. ("true" is a fixed value perhaps depending on the language.) */ /* If first arg is constant true, return it. */ if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0)) return arg0; case TRUTH_OR_EXPR: /* If either arg is constant zero, drop it. */ if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0)) return arg1; if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)) return arg0; /* Both known to be true => return true. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) return arg0; return t; case EQ_EXPR: case NE_EXPR: case LT_EXPR: case GT_EXPR: case LE_EXPR: case GE_EXPR: /* If one arg is a constant integer, put it last. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) != INTEGER_CST) { TREE_OPERAND (t, 0) = arg1; TREE_OPERAND (t, 1) = arg0; arg0 = TREE_OPERAND (t, 0); arg1 = TREE_OPERAND (t, 1); switch (code) { case GT_EXPR: code = LT_EXPR; break; case GE_EXPR: code = LE_EXPR; break; case LT_EXPR: code = GT_EXPR; break; case LE_EXPR: code = GE_EXPR; break; } TREE_SET_CODE (t, code); } /* Convert foo++ == CONST into ++foo == CONST + INCR. First, see if one arg is constant; find the constant arg and the other one. */ { tree constop = 0, varop; tree *constoploc; if (TREE_LITERAL (arg1)) constoploc = &TREE_OPERAND (t, 1), constop = arg1, varop = arg0; if (TREE_LITERAL (arg0)) constoploc = &TREE_OPERAND (t, 0), constop = arg0, varop = arg1; if (constop && TREE_CODE (varop) == POSTINCREMENT_EXPR) { tree newconst = fold (build (PLUS_EXPR, TREE_TYPE (constop), constop, TREE_OPERAND (varop, 1))); /* This optimization is invalid for ordered comparisons if CONST+INCR overflows or if foo+incr might overflow. For pointer types we assume overflow doesn't happen. */ if (TREE_CODE (TREE_TYPE (varop)) == POINTER_TYPE || code == EQ_EXPR || code == NE_EXPR) { /* This optimization is invalid for floating point if adding one to the constant does not change it. */ if (TREE_CODE (TREE_TYPE (newconst)) != REAL_TYPE || !REAL_VALUES_EQUAL (TREE_REAL_CST (newconst), TREE_REAL_CST (constop))) { TREE_SET_CODE (varop, PREINCREMENT_EXPR); *constoploc = newconst; return t; } } } else if (constop && TREE_CODE (varop) == POSTDECREMENT_EXPR) { tree newconst = fold (build (MINUS_EXPR, TREE_TYPE (constop), constop, TREE_OPERAND (varop, 1))); if (TREE_CODE (TREE_TYPE (varop)) == POINTER_TYPE || code == EQ_EXPR || code == NE_EXPR) { if (TREE_CODE (TREE_TYPE (newconst)) != REAL_TYPE || !REAL_VALUES_EQUAL (TREE_REAL_CST (newconst), TREE_REAL_CST (constop))) { TREE_SET_CODE (varop, PREDECREMENT_EXPR); *constoploc = newconst; return t; } } } } /* Change X >= CST to X > (CST - 1) if CST is positive. */ if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) != INTEGER_CST && ! tree_int_cst_lt (arg1, integer_one_node)) { switch (TREE_CODE (t)) { case GE_EXPR: code = GT_EXPR; TREE_SET_CODE (t, code); arg1 = combine (MINUS_EXPR, arg1, integer_one_node); TREE_OPERAND (t, 1) = arg1; break; case LT_EXPR: code = LE_EXPR; TREE_SET_CODE (t, code); arg1 = combine (MINUS_EXPR, arg1, integer_one_node); TREE_OPERAND (t, 1) = arg1; } } /* An unsigned comparison against 0 can be simplified. */ if (integer_zerop (arg1) && (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE || TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE) && TREE_UNSIGNED (TREE_TYPE (arg1))) { switch (TREE_CODE (t)) { case GT_EXPR: TREE_SET_CODE (t, NE_EXPR); break; case LE_EXPR: TREE_SET_CODE (t, EQ_EXPR); break; case GE_EXPR: return build (COMPOUND_EXPR, integer_type_node, arg0, integer_one_node); case LT_EXPR: return build (COMPOUND_EXPR, integer_type_node, arg0, integer_zero_node); } } /* To compute GT, swap the arguments and do LT. To compute GE, do LT and invert the result. To compute LE, swap the arguments, do LT and invert the result. To compute NE, do EQ and invert the result. */ if (code == LE_EXPR || code == GT_EXPR) { register tree temp = arg0; arg0 = arg1; arg1 = temp; } /* Compute a result for LT or EQ if args permit; otherwise return T. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) { if (code == EQ_EXPR || code == NE_EXPR) t = build_int_2 (TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1) && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1), 0); else t = build_int_2 ((TREE_UNSIGNED (TREE_TYPE (arg0)) ? INT_CST_LT_UNSIGNED (arg0, arg1) : INT_CST_LT (arg0, arg1)), 0); } else if (TREE_CODE (arg1) == INTEGER_CST && TREE_LITERAL (arg0) && TREE_CODE (arg0) == ADDR_EXPR && (code == EQ_EXPR || code == NE_EXPR)) { t = build_int_2 (0, 0); } else if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST) { if (code == EQ_EXPR || code == NE_EXPR) t = build_int_2 (REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), TREE_REAL_CST (arg1)), 0); else t = build_int_2 (REAL_VALUES_LESS (TREE_REAL_CST (arg0), TREE_REAL_CST (arg1)), 0); } else return t; /* If what we want is other than LT or EQ, invert the result. */ if (code == GE_EXPR || code == LE_EXPR || code == NE_EXPR) TREE_INT_CST_LOW (t) ^= 1; TREE_TYPE (t) = type; return t; case COND_EXPR: if (TREE_LITERAL (arg0)) return TREE_OPERAND (expr, (integer_zerop (arg0) ? 2 : 1)); return t; default: return t; } /* switch (code) */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -