void aff_combination_scale (aff_tree *comb, double_int scale) { unsigned i, j; scale = double_int_ext_for_comb (scale, comb); if (double_int_one_p (scale)) return; if (double_int_zero_p (scale)) { aff_combination_zero (comb, comb->type); return; } comb->offset = double_int_ext_for_comb (double_int_mul (scale, comb->offset), comb); for (i = 0, j = 0; i < comb->n; i++) { double_int new_coef; new_coef = double_int_ext_for_comb (double_int_mul (scale, comb->elts[i].coef), comb); /* A coefficient may become zero due to overflow. Remove the zero elements. */ if (double_int_zero_p (new_coef)) continue; comb->elts[j].coef = new_coef; comb->elts[j].val = comb->elts[i].val; j++; } comb->n = j; if (comb->rest) { tree type = comb->type; if (POINTER_TYPE_P (type)) type = sizetype; if (comb->n < MAX_AFF_ELTS) { comb->elts[comb->n].coef = scale; comb->elts[comb->n].val = comb->rest; comb->rest = NULL_TREE; comb->n++; } else comb->rest = fold_build2 (MULT_EXPR, type, comb->rest, double_int_to_tree (type, scale)); } }
static tree add_elt_to_tree (tree expr, tree type, tree elt, double_int scale, aff_tree *comb) { enum tree_code code; tree type1 = type; if (POINTER_TYPE_P (type)) type1 = sizetype; scale = double_int_ext_for_comb (scale, comb); elt = fold_convert (type1, elt); if (scale.is_one ()) { if (!expr) return fold_convert (type, elt); if (POINTER_TYPE_P (type)) return fold_build_pointer_plus (expr, elt); return fold_build2 (PLUS_EXPR, type, expr, elt); } if (scale.is_minus_one ()) { if (!expr) return fold_convert (type, fold_build1 (NEGATE_EXPR, type1, elt)); if (POINTER_TYPE_P (type)) { elt = fold_build1 (NEGATE_EXPR, type1, elt); return fold_build_pointer_plus (expr, elt); } return fold_build2 (MINUS_EXPR, type, expr, elt); } if (!expr) return fold_convert (type, fold_build2 (MULT_EXPR, type1, elt, double_int_to_tree (type1, scale))); if (scale.is_negative ()) { code = MINUS_EXPR; scale = -scale; } else code = PLUS_EXPR; elt = fold_build2 (MULT_EXPR, type1, elt, double_int_to_tree (type1, scale)); if (POINTER_TYPE_P (type)) { if (code == MINUS_EXPR) elt = fold_build1 (NEGATE_EXPR, type1, elt); return fold_build_pointer_plus (expr, elt); } return fold_build2 (code, type, expr, elt); }
void aff_combination_convert (aff_tree *comb, tree type) { unsigned i, j; tree comb_type = comb->type; if (TYPE_PRECISION (type) > TYPE_PRECISION (comb_type)) { tree val = fold_convert (type, aff_combination_to_tree (comb)); tree_to_aff_combination (val, type, comb); return; } comb->type = type; if (comb->rest && !POINTER_TYPE_P (type)) comb->rest = fold_convert (type, comb->rest); if (TYPE_PRECISION (type) == TYPE_PRECISION (comb_type)) return; comb->offset = double_int_ext_for_comb (comb->offset, comb); for (i = j = 0; i < comb->n; i++) { double_int new_coef = double_int_ext_for_comb (comb->elts[i].coef, comb); if (new_coef.is_zero ()) continue; comb->elts[j].coef = new_coef; comb->elts[j].val = fold_convert (type, comb->elts[i].val); j++; } comb->n = j; if (comb->n < MAX_AFF_ELTS && comb->rest) { comb->elts[comb->n].coef = double_int_one; comb->elts[comb->n].val = comb->rest; comb->rest = NULL_TREE; comb->n++; } }
static tree add_elt_to_tree (tree expr, tree type, tree elt, double_int scale, aff_tree *comb) { enum tree_code code; scale = double_int_ext_for_comb (scale, comb); elt = fold_convert (type, elt); if (double_int_one_p (scale)) { if (!expr) return elt; return fold_build2 (PLUS_EXPR, type, expr, elt); } if (double_int_minus_one_p (scale)) { if (!expr) return fold_build1 (NEGATE_EXPR, type, elt); return fold_build2 (MINUS_EXPR, type, expr, elt); } if (!expr) return fold_build2 (MULT_EXPR, type, elt, double_int_to_tree (type, scale)); if (double_int_negative_p (scale)) { code = MINUS_EXPR; scale = double_int_neg (scale); } else code = PLUS_EXPR; elt = fold_build2 (MULT_EXPR, type, elt, double_int_to_tree (type, scale)); return fold_build2 (code, type, expr, elt); }
static void most_expensive_mult_to_index (tree type, struct mem_address *parts, aff_tree *addr, bool speed) { addr_space_t as = TYPE_ADDR_SPACE (type); enum machine_mode address_mode = targetm.addr_space.address_mode (as); HOST_WIDE_INT coef; double_int best_mult, amult, amult_neg; unsigned best_mult_cost = 0, acost; tree mult_elt = NULL_TREE, elt; unsigned i, j; enum tree_code op_code; best_mult = double_int_zero; for (i = 0; i < addr->n; i++) { if (!double_int_fits_in_shwi_p (addr->elts[i].coef)) continue; coef = double_int_to_shwi (addr->elts[i].coef); if (coef == 1 || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as)) continue; acost = multiply_by_cost (coef, address_mode, speed); if (acost > best_mult_cost) { best_mult_cost = acost; best_mult = addr->elts[i].coef; } } if (!best_mult_cost) return; /* Collect elements multiplied by best_mult. */ for (i = j = 0; i < addr->n; i++) { amult = addr->elts[i].coef; amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr); if (double_int_equal_p (amult, best_mult)) op_code = PLUS_EXPR; else if (double_int_equal_p (amult_neg, best_mult)) op_code = MINUS_EXPR; else { addr->elts[j] = addr->elts[i]; j++; continue; } elt = fold_convert (sizetype, addr->elts[i].val); if (mult_elt) mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt); else if (op_code == PLUS_EXPR) mult_elt = elt; else mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt); } addr->n = j; parts->index = mult_elt; parts->step = double_int_to_tree (sizetype, best_mult); }
void aff_combination_const (aff_tree *comb, tree type, double_int cst) { aff_combination_zero (comb, type); comb->offset = double_int_ext_for_comb (cst, comb); }
static void aff_combination_add_cst (aff_tree *c, double_int cst) { c->offset = double_int_ext_for_comb (c->offset + cst, c); }
void aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale) { unsigned i; tree type; scale = double_int_ext_for_comb (scale, comb); if (scale.is_zero ()) return; for (i = 0; i < comb->n; i++) if (operand_equal_p (comb->elts[i].val, elt, 0)) { double_int new_coef; new_coef = comb->elts[i].coef + scale; new_coef = double_int_ext_for_comb (new_coef, comb); if (!new_coef.is_zero ()) { comb->elts[i].coef = new_coef; return; } comb->n--; comb->elts[i] = comb->elts[comb->n]; if (comb->rest) { gcc_assert (comb->n == MAX_AFF_ELTS - 1); comb->elts[comb->n].coef = double_int_one; comb->elts[comb->n].val = comb->rest; comb->rest = NULL_TREE; comb->n++; } return; } if (comb->n < MAX_AFF_ELTS) { comb->elts[comb->n].coef = scale; comb->elts[comb->n].val = elt; comb->n++; return; } type = comb->type; if (POINTER_TYPE_P (type)) type = sizetype; if (scale.is_one ()) elt = fold_convert (type, elt); else elt = fold_build2 (MULT_EXPR, type, fold_convert (type, elt), double_int_to_tree (type, scale)); if (comb->rest) comb->rest = fold_build2 (PLUS_EXPR, type, comb->rest, elt); else comb->rest = elt; }
static tree add_elt_to_tree (tree expr, tree type, tree elt, double_int scale, aff_tree *comb) { enum tree_code code; tree type1 = type; if (POINTER_TYPE_P (type)) #ifdef TARGET_POINTER_SIZETYPE { /* sizetype is not good enough for pointers in ADDRESS_SPACES on dsPIC; some pointers are larger than 'sizetype' (CAW) */ type1 = TARGET_POINTER_SIZETYPE(type); } #else type1 = sizetype; #endif scale = double_int_ext_for_comb (scale, comb); elt = fold_convert (type1, elt); if (double_int_one_p (scale)) { if (!expr) return fold_convert (type, elt); if (POINTER_TYPE_P (type)) return fold_build2 (POINTER_PLUS_EXPR, type, expr, elt); return fold_build2 (PLUS_EXPR, type, expr, elt); } if (double_int_minus_one_p (scale)) { if (!expr) return fold_convert (type, fold_build1 (NEGATE_EXPR, type1, elt)); if (POINTER_TYPE_P (type)) { elt = fold_build1 (NEGATE_EXPR, type1, elt); return fold_build2 (POINTER_PLUS_EXPR, type, expr, elt); } return fold_build2 (MINUS_EXPR, type, expr, elt); } if (!expr) return fold_convert (type, fold_build2 (MULT_EXPR, type1, elt, double_int_to_tree (type1, scale))); if (double_int_negative_p (scale)) { code = MINUS_EXPR; scale = double_int_neg (scale); } else code = PLUS_EXPR; elt = fold_build2 (MULT_EXPR, type1, elt, double_int_to_tree (type1, scale)); if (POINTER_TYPE_P (type)) { if (code == MINUS_EXPR) elt = fold_build1 (NEGATE_EXPR, type1, elt); return fold_build2 (POINTER_PLUS_EXPR, type, expr, elt); } return fold_build2 (code, type, expr, elt); }