static inline tree chrec_fold_plus_poly_poly (enum tree_code code, tree type, tree poly0, tree poly1) { tree left, right; struct loop *loop0 = get_chrec_loop (poly0); struct loop *loop1 = get_chrec_loop (poly1); tree rtype = code == POINTER_PLUS_EXPR ? chrec_type (poly1) : type; gcc_assert (poly0); gcc_assert (poly1); gcc_assert (TREE_CODE (poly0) == POLYNOMIAL_CHREC); gcc_assert (TREE_CODE (poly1) == POLYNOMIAL_CHREC); if (POINTER_TYPE_P (chrec_type (poly0))) gcc_checking_assert (ptrofftype_p (chrec_type (poly1)) && useless_type_conversion_p (type, chrec_type (poly0))); else gcc_checking_assert (useless_type_conversion_p (type, chrec_type (poly0)) && useless_type_conversion_p (type, chrec_type (poly1))); /* {a, +, b}_1 + {c, +, d}_2 -> {{a, +, b}_1 + c, +, d}_2, {a, +, b}_2 + {c, +, d}_1 -> {{c, +, d}_1 + a, +, b}_2, {a, +, b}_x + {c, +, d}_x -> {a+c, +, b+d}_x. */ if (flow_loop_nested_p (loop0, loop1)) { if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (poly1), chrec_fold_plus (type, poly0, CHREC_LEFT (poly1)), CHREC_RIGHT (poly1)); else return build_polynomial_chrec (CHREC_VARIABLE (poly1), chrec_fold_minus (type, poly0, CHREC_LEFT (poly1)), chrec_fold_multiply (type, CHREC_RIGHT (poly1), SCALAR_FLOAT_TYPE_P (type) ? build_real (type, dconstm1) : build_int_cst_type (type, -1))); } if (flow_loop_nested_p (loop1, loop0)) { if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (poly0), chrec_fold_plus (type, CHREC_LEFT (poly0), poly1), CHREC_RIGHT (poly0)); else return build_polynomial_chrec (CHREC_VARIABLE (poly0), chrec_fold_minus (type, CHREC_LEFT (poly0), poly1), CHREC_RIGHT (poly0)); } /* This function should never be called for chrecs of loops that do not belong to the same loop nest. */ gcc_assert (loop0 == loop1); if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) { left = chrec_fold_plus (type, CHREC_LEFT (poly0), CHREC_LEFT (poly1)); right = chrec_fold_plus (rtype, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1)); } else { left = chrec_fold_minus (type, CHREC_LEFT (poly0), CHREC_LEFT (poly1)); right = chrec_fold_minus (type, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1)); } if (chrec_zerop (right)) return left; else return build_polynomial_chrec (CHREC_VARIABLE (poly0), left, right); }
static inline tree chrec_fold_plus_poly_poly (enum tree_code code, tree type, tree poly0, tree poly1) { tree left, right; gcc_assert (poly0); gcc_assert (poly1); gcc_assert (TREE_CODE (poly0) == POLYNOMIAL_CHREC); gcc_assert (TREE_CODE (poly1) == POLYNOMIAL_CHREC); gcc_assert (chrec_type (poly0) == chrec_type (poly1)); gcc_assert (type == chrec_type (poly0)); /* {a, +, b}_1 + {c, +, d}_2 -> {{a, +, b}_1 + c, +, d}_2, {a, +, b}_2 + {c, +, d}_1 -> {{c, +, d}_1 + a, +, b}_2, {a, +, b}_x + {c, +, d}_x -> {a+c, +, b+d}_x. */ if (CHREC_VARIABLE (poly0) < CHREC_VARIABLE (poly1)) { if (code == PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (poly1), chrec_fold_plus (type, poly0, CHREC_LEFT (poly1)), CHREC_RIGHT (poly1)); else return build_polynomial_chrec (CHREC_VARIABLE (poly1), chrec_fold_minus (type, poly0, CHREC_LEFT (poly1)), chrec_fold_multiply (type, CHREC_RIGHT (poly1), SCALAR_FLOAT_TYPE_P (type) ? build_real (type, dconstm1) : build_int_cst_type (type, -1))); } if (CHREC_VARIABLE (poly0) > CHREC_VARIABLE (poly1)) { if (code == PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (poly0), chrec_fold_plus (type, CHREC_LEFT (poly0), poly1), CHREC_RIGHT (poly0)); else return build_polynomial_chrec (CHREC_VARIABLE (poly0), chrec_fold_minus (type, CHREC_LEFT (poly0), poly1), CHREC_RIGHT (poly0)); } if (code == PLUS_EXPR) { left = chrec_fold_plus (type, CHREC_LEFT (poly0), CHREC_LEFT (poly1)); right = chrec_fold_plus (type, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1)); } else { left = chrec_fold_minus (type, CHREC_LEFT (poly0), CHREC_LEFT (poly1)); right = chrec_fold_minus (type, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1)); } if (chrec_zerop (right)) return left; else return build_polynomial_chrec (CHREC_VARIABLE (poly0), left, right); }