return fold_build2_loc (loc, code, type, arg0_inner, arg1);
}
-/* Tries to replace &a[idx] p+ s * delta with &a[idx + delta], if s is
- step of the array. Reconstructs s and delta in the case of s *
- delta being an integer constant (and thus already folded). ADDR is
- the address. MULT is the multiplicative expression. If the
- function succeeds, the new address expression is returned.
- Otherwise NULL_TREE is returned. LOC is the location of the
- resulting expression. */
-
-static tree
-try_move_mult_to_index (location_t loc, tree addr, tree op1)
-{
- tree s, delta, step;
- tree ref = TREE_OPERAND (addr, 0), pref;
- tree ret, pos;
- tree itype;
- bool mdim = false;
-
- /* Strip the nops that might be added when converting op1 to sizetype. */
- STRIP_NOPS (op1);
-
- /* Canonicalize op1 into a possibly non-constant delta
- and an INTEGER_CST s. */
- if (TREE_CODE (op1) == MULT_EXPR)
- {
- tree arg0 = TREE_OPERAND (op1, 0), arg1 = TREE_OPERAND (op1, 1);
-
- STRIP_NOPS (arg0);
- STRIP_NOPS (arg1);
-
- if (TREE_CODE (arg0) == INTEGER_CST)
- {
- s = arg0;
- delta = arg1;
- }
- else if (TREE_CODE (arg1) == INTEGER_CST)
- {
- s = arg1;
- delta = arg0;
- }
- else
- return NULL_TREE;
- }
- else if (TREE_CODE (op1) == INTEGER_CST)
- {
- delta = op1;
- s = NULL_TREE;
- }
- else
- {
- /* Simulate we are delta * 1. */
- delta = op1;
- s = integer_one_node;
- }
-
- /* Handle &x.array the same as we would handle &x.array[0]. */
- if (TREE_CODE (ref) == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
- {
- tree domain;
-
- /* Remember if this was a multi-dimensional array. */
- if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
- mdim = true;
-
- domain = TYPE_DOMAIN (TREE_TYPE (ref));
- if (! domain)
- goto cont;
- itype = TREE_TYPE (domain);
-
- step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
- if (TREE_CODE (step) != INTEGER_CST)
- goto cont;
-
- if (s)
- {
- if (! tree_int_cst_equal (step, s))
- goto cont;
- }
- else
- {
- /* Try if delta is a multiple of step. */
- tree tmp = div_if_zero_remainder (op1, step);
- if (! tmp)
- goto cont;
- delta = tmp;
- }
-
- /* Only fold here if we can verify we do not overflow one
- dimension of a multi-dimensional array. */
- if (mdim)
- {
- tree tmp;
-
- if (!TYPE_MIN_VALUE (domain)
- || !TYPE_MAX_VALUE (domain)
- || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
- goto cont;
-
- tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
- fold_convert_loc (loc, itype,
- TYPE_MIN_VALUE (domain)),
- fold_convert_loc (loc, itype, delta));
- if (TREE_CODE (tmp) != INTEGER_CST
- || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
- goto cont;
- }
-
- /* We found a suitable component reference. */
-
- pref = TREE_OPERAND (addr, 0);
- ret = copy_node (pref);
- SET_EXPR_LOCATION (ret, loc);
-
- ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
- fold_build2_loc
- (loc, PLUS_EXPR, itype,
- fold_convert_loc (loc, itype,
- TYPE_MIN_VALUE
- (TYPE_DOMAIN (TREE_TYPE (ref)))),
- fold_convert_loc (loc, itype, delta)),
- NULL_TREE, NULL_TREE);
- return build_fold_addr_expr_loc (loc, ret);
- }
-
-cont:
-
- for (;; ref = TREE_OPERAND (ref, 0))
- {
- if (TREE_CODE (ref) == ARRAY_REF)
- {
- tree domain;
-
- /* Remember if this was a multi-dimensional array. */
- if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
- mdim = true;
-
- domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
- if (! domain)
- continue;
- itype = TREE_TYPE (domain);
-
- step = array_ref_element_size (ref);
- if (TREE_CODE (step) != INTEGER_CST)
- continue;
-
- if (s)
- {
- if (! tree_int_cst_equal (step, s))
- continue;
- }
- else
- {
- /* Try if delta is a multiple of step. */
- tree tmp = div_if_zero_remainder (op1, step);
- if (! tmp)
- continue;
- delta = tmp;
- }
-
- /* Only fold here if we can verify we do not overflow one
- dimension of a multi-dimensional array. */
- if (mdim)
- {
- tree tmp;
-
- if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
- || !TYPE_MAX_VALUE (domain)
- || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
- continue;
-
- tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
- fold_convert_loc (loc, itype,
- TREE_OPERAND (ref, 1)),
- fold_convert_loc (loc, itype, delta));
- if (!tmp
- || TREE_CODE (tmp) != INTEGER_CST
- || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
- continue;
- }
-
- break;
- }
- else
- mdim = false;
-
- if (!handled_component_p (ref))
- return NULL_TREE;
- }
-
- /* We found the suitable array reference. So copy everything up to it,
- and replace the index. */
-
- pref = TREE_OPERAND (addr, 0);
- ret = copy_node (pref);
- SET_EXPR_LOCATION (ret, loc);
- pos = ret;
-
- while (pref != ref)
- {
- pref = TREE_OPERAND (pref, 0);
- TREE_OPERAND (pos, 0) = copy_node (pref);
- pos = TREE_OPERAND (pos, 0);
- }
-
- TREE_OPERAND (pos, 1)
- = fold_build2_loc (loc, PLUS_EXPR, itype,
- fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
- fold_convert_loc (loc, itype, delta));
- return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
-}
-
/* Fold A < X && A + 1 > Y to A < X && A >= Y. Normally A + 1 > Y
means A >= Y && A != MAX, but in this case we know that
return fold_build2_loc (loc, PLUS_EXPR, type, arg0,
fold_convert_loc (loc, type, arg1));
- /* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step
- of the array. Loop optimizer sometimes produce this type of
- expressions. */
- if (TREE_CODE (arg0) == ADDR_EXPR)
- {
- tem = try_move_mult_to_index (loc, arg0,
- fold_convert_loc (loc,
- ssizetype, arg1));
- if (tem)
- return fold_convert_loc (loc, type, tem);
- }
-
return NULL_TREE;
case PLUS_EXPR: