fold-const.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,288 行 · 第 1/5 页
C
2,288 行
return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0); case '<': case '2': if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0) && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0)) return 1; /* For commutative ops, allow the other order. */ return ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MULT_EXPR || TREE_CODE (arg0) == MIN_EXPR || TREE_CODE (arg0) == MAX_EXPR || TREE_CODE (arg0) == BIT_IOR_EXPR || TREE_CODE (arg0) == BIT_XOR_EXPR || TREE_CODE (arg0) == BIT_AND_EXPR || TREE_CODE (arg0) == NE_EXPR || TREE_CODE (arg0) == EQ_EXPR) && operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 1), 0) && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 0), 0)); case 'r': switch (TREE_CODE (arg0)) { case INDIRECT_REF: return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0); case COMPONENT_REF: case ARRAY_REF: return (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0) && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0)); case BIT_FIELD_REF: return (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0) && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0) && operand_equal_p (TREE_OPERAND (arg0, 2), TREE_OPERAND (arg1, 2), 0)); default: return 0; } default: return 0; }}/* Similar to operand_equal_p, but see if ARG0 might have been made by shorten_compare from ARG1 when ARG1 was being compared with OTHER. When in doubt, return 0. */static int operand_equal_for_comparison_p (arg0, arg1, other) tree arg0, arg1; tree other;{ int unsignedp1, unsignedpo; tree primarg1, primother; unsigned correct_width; if (operand_equal_p (arg0, arg1, 0)) return 1; if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0)) || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1))) return 0; /* Duplicate what shorten_compare does to ARG1 and see if that gives the actual comparison operand, ARG0. First throw away any conversions to wider types already present in the operands. */ primarg1 = get_narrower (arg1, &unsignedp1); primother = get_narrower (other, &unsignedpo); correct_width = TYPE_PRECISION (TREE_TYPE (arg1)); if (unsignedp1 == unsignedpo && TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width && TYPE_PRECISION (TREE_TYPE (primother)) < correct_width) { tree type = TREE_TYPE (arg0); /* Make sure shorter operand is extended the right way to match the longer operand. */ primarg1 = convert (signed_or_unsigned_type (unsignedp1, TREE_TYPE (primarg1)), primarg1); if (operand_equal_p (arg0, convert (type, primarg1), 0)) return 1; } return 0;}/* See if ARG is an expression that is either a comparison or is performing arithmetic on comparisons. The comparisons must only be comparing two different values, which will be stored in *CVAL1 and *CVAL2; if they are non-zero it means that some operands have already been found. No variables may be used anywhere else in the expression except in the comparisons. If SAVE_P is true it means we removed a SAVE_EXPR around the expression and save_expr needs to be called with CVAL1 and CVAL2. If this is true, return 1. Otherwise, return zero. */static inttwoval_comparison_p (arg, cval1, cval2, save_p) tree arg; tree *cval1, *cval2; int *save_p;{ enum tree_code code = TREE_CODE (arg); char class = TREE_CODE_CLASS (code); /* We can handle some of the 'e' cases here. */ if (class == 'e' && code == TRUTH_NOT_EXPR) class = '1'; else if (class == 'e' && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR || code == COMPOUND_EXPR)) class = '2'; /* ??? Disable this since the SAVE_EXPR might already be in use outside the expression. There may be no way to make this work, but it needs to be looked at again for 2.6. */#if 0 else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0) { /* If we've already found a CVAL1 or CVAL2, this expression is two complex to handle. */ if (*cval1 || *cval2) return 0; class = '1'; *save_p = 1; }#endif switch (class) { case '1': return twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p); case '2': return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p) && twoval_comparison_p (TREE_OPERAND (arg, 1), cval1, cval2, save_p)); case 'c': return 1; case 'e': if (code == COND_EXPR) return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p) && twoval_comparison_p (TREE_OPERAND (arg, 1), cval1, cval2, save_p) && twoval_comparison_p (TREE_OPERAND (arg, 2), cval1, cval2, save_p)); return 0; case '<': /* First see if we can handle the first operand, then the second. For the second operand, we know *CVAL1 can't be zero. It must be that one side of the comparison is each of the values; test for the case where this isn't true by failing if the two operands are the same. */ if (operand_equal_p (TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1), 0)) return 0; if (*cval1 == 0) *cval1 = TREE_OPERAND (arg, 0); else if (operand_equal_p (*cval1, TREE_OPERAND (arg, 0), 0)) ; else if (*cval2 == 0) *cval2 = TREE_OPERAND (arg, 0); else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 0), 0)) ; else return 0; if (operand_equal_p (*cval1, TREE_OPERAND (arg, 1), 0)) ; else if (*cval2 == 0) *cval2 = TREE_OPERAND (arg, 1); else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 1), 0)) ; else return 0; return 1; default: return 0; }}/* ARG is a tree that is known to contain just arithmetic operations and comparisons. Evaluate the operations in the tree substituting NEW0 for any occurrence of OLD0 as an operand of a comparison and likewise for NEW1 and OLD1. */static treeeval_subst (arg, old0, new0, old1, new1) tree arg; tree old0, new0, old1, new1;{ tree type = TREE_TYPE (arg); enum tree_code code = TREE_CODE (arg); char class = TREE_CODE_CLASS (code); /* We can handle some of the 'e' cases here. */ if (class == 'e' && code == TRUTH_NOT_EXPR) class = '1'; else if (class == 'e' && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)) class = '2'; switch (class) { case '1': return fold (build1 (code, type, eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1))); case '2': return fold (build (code, type, eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1), eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1))); case 'e': switch (code) { case SAVE_EXPR: return eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1); case COMPOUND_EXPR: return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1); case COND_EXPR: return fold (build (code, type, eval_subst (TREE_OPERAND (arg, 0), old0, new0, old1, new1), eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1), eval_subst (TREE_OPERAND (arg, 2), old0, new0, old1, new1))); default: break; } /* fall through (???) */ case '<': { tree arg0 = TREE_OPERAND (arg, 0); tree arg1 = TREE_OPERAND (arg, 1); /* We need to check both for exact equality and tree equality. The former will be true if the operand has a side-effect. In that case, we know the operand occurred exactly once. */ if (arg0 == old0 || operand_equal_p (arg0, old0, 0)) arg0 = new0; else if (arg0 == old1 || operand_equal_p (arg0, old1, 0)) arg0 = new1; if (arg1 == old0 || operand_equal_p (arg1, old0, 0)) arg1 = new0; else if (arg1 == old1 || operand_equal_p (arg1, old1, 0)) arg1 = new1; return fold (build (code, type, arg0, arg1)); } default: return arg; }}/* Return a tree for the case when the result of an expression is RESULT converted to TYPE and OMITTED was previously an operand of the expression but is now not needed (e.g., we folded OMITTED * 0). If OMITTED has side effects, we must evaluate it. Otherwise, just do the conversion of RESULT to TYPE. */static treeomit_one_operand (type, result, omitted) tree type, result, omitted;{ tree t = convert (type, result); if (TREE_SIDE_EFFECTS (omitted)) return build (COMPOUND_EXPR, type, omitted, t); return non_lvalue (t);}/* Similar, but call pedantic_non_lvalue instead of non_lvalue. */static treepedantic_omit_one_operand (type, result, omitted) tree type, result, omitted;{ tree t = convert (type, result); if (TREE_SIDE_EFFECTS (omitted)) return build (COMPOUND_EXPR, type, omitted, t); return pedantic_non_lvalue (t);}/* Return a simplified tree node for the truth-negation of ARG. This never alters ARG itself. We assume that ARG is an operation that returns a truth value (0 or 1). */treeinvert_truthvalue (arg) tree arg;{ tree type = TREE_TYPE (arg); enum tree_code code = TREE_CODE (arg); if (code == ERROR_MARK) return arg; /* If this is a comparison, we can simply invert it, except for floating-point non-equality comparisons, in which case we just enclose a TRUTH_NOT_EXPR around what we have. */ if (TREE_CODE_CLASS (code) == '<') { if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0))) && code != NE_EXPR && code != EQ_EXPR) return build1 (TRUTH_NOT_EXPR, type, arg); else return build (invert_tree_comparison (code), type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); } switch (code) { case INTEGER_CST: return convert (type, build_int_2 (TREE_INT_CST_LOW (arg) == 0 && TREE_INT_CST_HIGH (arg) == 0, 0)); case TRUTH_AND_EXPR: return build (TRUTH_OR_EXPR, type, invert_truthvalue (TREE_OPERAND (arg, 0)), invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_OR_EXPR: return build (TRUTH_AND_EXPR, type, invert_truthvalue (TREE_OPERAND (arg, 0)), invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_XOR_EXPR: /* Here we can invert either operand. We invert the first operand unless the second operand is a TRUTH_NOT_EXPR in which case our result is the XOR of the first operand with the inside of the negation of the second operand. */ if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR) return build (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0), TREE_OPERAND (TREE_OPERAND (arg, 1), 0)); else return build (TRUTH_XOR_EXPR, type, invert_truthvalue (TREE_OPERAND (arg, 0)), TREE_OPERAND (arg, 1)); case TRUTH_ANDIF_EXPR: return build (TRUTH_ORIF_EXPR, type, invert_truthvalue (TREE_OPERAND (arg, 0)), invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_ORIF_EXPR: return build (TRUTH_ANDIF_EXPR, type, invert_truthvalue (TREE_OPERAND (arg, 0)), invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_NOT_EXPR: return TREE_OPERAND (arg, 0); case COND_EXPR: return build (COND_EXPR, type, TREE_OPERAND (arg, 0), invert_truthvalue (TREE_OPERAND (arg, 1)), invert_truthvalue (TREE_OPERAND (arg, 2))); case COMPOUND_EXPR: return build (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0), invert_truthvalue (TREE_OPERAND (arg, 1))); case NON_LVALUE_EXPR: return invert_truthvalue (TREE_OPERAND (arg, 0)); case NOP_EXPR: case CONVERT_EXPR: case FLOAT_EXPR: return build1 (TREE_CODE (arg), type, invert_truthvalue (TREE_OPERAND (arg, 0))); case BIT_AND_EXPR: if (!integer_onep (TREE_OPERAND (arg, 1))) break; return build (EQ_EXPR, type, arg, convert (type, integer_zero_node)); case SAVE_EXPR: return build1 (TRUTH_NOT_EXPR, type, arg); case CLEANUP_POINT_EXPR: return build1 (CLEANUP_POINT_EXPR, type, invert_truthvalue (TREE_OPERAND (arg, 0))); default: break; } if (TREE_CODE (TREE_TYPE (arg)) != BOOLEAN_TYPE) abort (); return build1 (TRUTH_NOT_EXPR, type, arg);}/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both operands are another bit-wise operation with a common input. If so, distribute the bit operations to save an operation and possibly two if constants are involved. For example, convert (A | B) & (A | C) into A | (B & C) Further simplification will occur if B and C are constants. If this optimization cannot be done, 0 will be returned. */static treedistribute_bit_expr (code, type, arg0, arg1) enum tree_code code; tree type; tree arg0, arg1;{ tree common; tree left, right; if (TREE_CODE (arg0) != TREE_CODE (arg1) || TREE_CODE (arg0) == code || (TREE_C
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?