tree chrec_fold_multiply (tree type, tree op0, tree op1) { if (automatically_generated_chrec_p (op0) || automatically_generated_chrec_p (op1)) return chrec_fold_automatically_generated_operands (op0, op1); switch (TREE_CODE (op0)) { case POLYNOMIAL_CHREC: switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: return chrec_fold_multiply_poly_poly (type, op0, op1); default: if (integer_onep (op1)) return op0; if (integer_zerop (op1)) return build_int_cst (type, 0); return build_polynomial_chrec (CHREC_VARIABLE (op0), chrec_fold_multiply (type, CHREC_LEFT (op0), op1), chrec_fold_multiply (type, CHREC_RIGHT (op0), op1)); } default: if (integer_onep (op0)) return op1; if (integer_zerop (op0)) return build_int_cst (type, 0); switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_multiply (type, CHREC_LEFT (op1), op0), chrec_fold_multiply (type, CHREC_RIGHT (op1), op0)); default: if (integer_onep (op1)) return op0; if (integer_zerop (op1)) return build_int_cst (type, 0); return fold_build2 (MULT_EXPR, type, op0, op1); } } }
tree chrec_fold_minus (tree type, tree op0, tree op1) { if (automatically_generated_chrec_p (op0) || automatically_generated_chrec_p (op1)) return chrec_fold_automatically_generated_operands (op0, op1); if (integer_zerop (op1)) return op0; return chrec_fold_plus_1 (MINUS_EXPR, type, op0, op1); }
tree chrec_fold_plus (tree type, tree op0, tree op1) { enum tree_code code; if (automatically_generated_chrec_p (op0) || automatically_generated_chrec_p (op1)) return chrec_fold_automatically_generated_operands (op0, op1); if (integer_zerop (op0)) return chrec_convert (type, op1, NULL); if (integer_zerop (op1)) return chrec_convert (type, op0, NULL); if (POINTER_TYPE_P (type)) code = POINTER_PLUS_EXPR; else code = PLUS_EXPR; return chrec_fold_plus_1 (code, type, op0, op1); }
tree chrec_fold_multiply (tree type, tree op0, tree op1) { if (automatically_generated_chrec_p (op0) || automatically_generated_chrec_p (op1)) return chrec_fold_automatically_generated_operands (op0, op1); switch (TREE_CODE (op0)) { case POLYNOMIAL_CHREC: gcc_checking_assert (!chrec_contains_symbols_defined_in_loop (op0, CHREC_VARIABLE (op0))); switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: gcc_checking_assert (!chrec_contains_symbols_defined_in_loop (op1, CHREC_VARIABLE (op1))); return chrec_fold_multiply_poly_poly (type, op0, op1); CASE_CONVERT: if (tree_contains_chrecs (op1, NULL)) return chrec_dont_know; default: if (integer_onep (op1)) return op0; if (integer_zerop (op1)) return build_int_cst (type, 0); return build_polynomial_chrec (CHREC_VARIABLE (op0), chrec_fold_multiply (type, CHREC_LEFT (op0), op1), chrec_fold_multiply (type, CHREC_RIGHT (op0), op1)); } CASE_CONVERT: if (tree_contains_chrecs (op0, NULL)) return chrec_dont_know; default: if (integer_onep (op0)) return op1; if (integer_zerop (op0)) return build_int_cst (type, 0); switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: gcc_checking_assert (!chrec_contains_symbols_defined_in_loop (op1, CHREC_VARIABLE (op1))); return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_multiply (type, CHREC_LEFT (op1), op0), chrec_fold_multiply (type, CHREC_RIGHT (op1), op0)); CASE_CONVERT: if (tree_contains_chrecs (op1, NULL)) return chrec_dont_know; default: if (integer_onep (op1)) return op0; if (integer_zerop (op1)) return build_int_cst (type, 0); return fold_build2 (MULT_EXPR, type, op0, op1); } } }
static tree chrec_fold_plus_1 (enum tree_code code, tree type, tree op0, tree op1) { if (automatically_generated_chrec_p (op0) || automatically_generated_chrec_p (op1)) return chrec_fold_automatically_generated_operands (op0, op1); switch (TREE_CODE (op0)) { case POLYNOMIAL_CHREC: gcc_checking_assert (!chrec_contains_symbols_defined_in_loop (op0, CHREC_VARIABLE (op0))); switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: gcc_checking_assert (!chrec_contains_symbols_defined_in_loop (op1, CHREC_VARIABLE (op1))); return chrec_fold_plus_poly_poly (code, type, op0, op1); CASE_CONVERT: if (tree_contains_chrecs (op1, NULL)) return chrec_dont_know; default: if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (op0), chrec_fold_plus (type, CHREC_LEFT (op0), op1), CHREC_RIGHT (op0)); else return build_polynomial_chrec (CHREC_VARIABLE (op0), chrec_fold_minus (type, CHREC_LEFT (op0), op1), CHREC_RIGHT (op0)); } CASE_CONVERT: if (tree_contains_chrecs (op0, NULL)) return chrec_dont_know; default: switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: gcc_checking_assert (!chrec_contains_symbols_defined_in_loop (op1, CHREC_VARIABLE (op1))); if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_plus (type, op0, CHREC_LEFT (op1)), CHREC_RIGHT (op1)); else return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_minus (type, op0, CHREC_LEFT (op1)), chrec_fold_multiply (type, CHREC_RIGHT (op1), SCALAR_FLOAT_TYPE_P (type) ? build_real (type, dconstm1) : build_int_cst_type (type, -1))); CASE_CONVERT: if (tree_contains_chrecs (op1, NULL)) return chrec_dont_know; default: { int size = 0; if ((tree_contains_chrecs (op0, &size) || tree_contains_chrecs (op1, &size)) && size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE)) return build2 (code, type, op0, op1); else if (size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE)) { if (code == POINTER_PLUS_EXPR) return fold_build_pointer_plus (fold_convert (type, op0), op1); else return fold_build2 (code, type, fold_convert (type, op0), fold_convert (type, op1)); } else return chrec_dont_know; } } } }
static tree chrec_fold_plus_1 (enum tree_code code, tree type, tree op0, tree op1) { if (automatically_generated_chrec_p (op0) || automatically_generated_chrec_p (op1)) return chrec_fold_automatically_generated_operands (op0, op1); switch (TREE_CODE (op0)) { case POLYNOMIAL_CHREC: switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: return chrec_fold_plus_poly_poly (code, type, op0, op1); default: if (code == PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (op0), chrec_fold_plus (type, CHREC_LEFT (op0), op1), CHREC_RIGHT (op0)); else return build_polynomial_chrec (CHREC_VARIABLE (op0), chrec_fold_minus (type, CHREC_LEFT (op0), op1), CHREC_RIGHT (op0)); } default: switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: if (code == PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_plus (type, op0, CHREC_LEFT (op1)), CHREC_RIGHT (op1)); else return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_minus (type, op0, CHREC_LEFT (op1)), chrec_fold_multiply (type, CHREC_RIGHT (op1), build_int_cst_type (type, -1))); default: { int size = 0; if ((tree_contains_chrecs (op0, &size) || tree_contains_chrecs (op1, &size)) && size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE)) return build2 (code, type, op0, op1); else if (size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE)) return fold (build2 (code, type, op0, op1)); else return chrec_dont_know; } } } }