diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2017-11-21 19:23:56 +0100 |
---|---|---|
committer | Marc Glisse <glisse@gcc.gnu.org> | 2017-11-21 18:23:56 +0000 |
commit | 1af4ebf5985ef2aaac13862654044d84a3cd7ae4 (patch) | |
tree | 6136f270e536b46d7d9de96d28e38794684035dd /gcc/fold-const.c | |
parent | ffb41aab7a9b8475e773b75fdebd194f4491c9db (diff) | |
download | gcc-1af4ebf5985ef2aaac13862654044d84a3cd7ae4.zip gcc-1af4ebf5985ef2aaac13862654044d84a3cd7ae4.tar.gz gcc-1af4ebf5985ef2aaac13862654044d84a3cd7ae4.tar.bz2 |
New POINTER_DIFF_EXPR
2017-11-21 Marc Glisse <marc.glisse@inria.fr>
gcc/c/
* c-fold.c (c_fully_fold_internal): Handle POINTER_DIFF_EXPR.
* c-typeck.c (pointer_diff): Use POINTER_DIFF_EXPR.
gcc/c-family/
* c-pretty-print.c (pp_c_additive_expression,
c_pretty_printer::expression): Handle POINTER_DIFF_EXPR.
gcc/cp/
* constexpr.c (cxx_eval_constant_expression,
potential_constant_expression_1): Handle POINTER_DIFF_EXPR.
* cp-gimplify.c (cp_fold): Likewise.
* error.c (dump_expr): Likewise.
* typeck.c (pointer_diff): Use POINTER_DIFF_EXPR.
gcc/
* doc/generic.texi: Document POINTER_DIFF_EXPR, update
POINTER_PLUS_EXPR.
* cfgexpand.c (expand_debug_expr): Handle POINTER_DIFF_EXPR.
* expr.c (expand_expr_real_2): Likewise.
* fold-const.c (const_binop, fold_addr_of_array_ref_difference,
fold_binary_loc): Likewise.
* match.pd (X-X, P+(Q-P), &D-P, (P+N)-P, P-(P+N), (P+M)-(P+N),
P-Q==0, -(A-B), X-Z<Y-Z, (X-Z)-(Y-Z), Z-X<Z-Y, (Z-X)-(Z-Y),
(A-B)+(C-A)): New transformations for POINTER_DIFF_EXPR, based on
MINUS_EXPR transformations.
* optabs-tree.c (optab_for_tree_code): Handle POINTER_DIFF_EXPR.
* tree-cfg.c (verify_expr, verify_gimple_assign_binary): Likewise.
* tree-inline.c (estimate_operator_cost): Likewise.
* tree-pretty-print.c (dump_generic_node, op_code_prio,
op_symbol_code): Likewise.
* tree-vect-stmts.c (vectorizable_operation): Likewise.
* vr-values.c (extract_range_from_binary_expr): Likewise.
* varasm.c (initializer_constant_valid_p_1): Likewise.
* tree.def: New tree code POINTER_DIFF_EXPR.
From-SVN: r255021
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e9cd968..9fe3462 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1483,6 +1483,16 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2) return build_complex (type, arg1, arg2); return NULL_TREE; + case POINTER_DIFF_EXPR: + if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST) + { + offset_int res = wi::sub (wi::to_offset (arg1), + wi::to_offset (arg2)); + return force_fit_type (type, res, 1, + TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)); + } + return NULL_TREE; + case VEC_PACK_TRUNC_EXPR: case VEC_PACK_FIX_TRUNC_EXPR: { @@ -8801,7 +8811,8 @@ fold_vec_perm (tree type, tree arg0, tree arg1, vec_perm_indices sel) static tree fold_addr_of_array_ref_difference (location_t loc, tree type, - tree aref0, tree aref1) + tree aref0, tree aref1, + bool use_pointer_diff) { tree base0 = TREE_OPERAND (aref0, 0); tree base1 = TREE_OPERAND (aref1, 0); @@ -8813,14 +8824,20 @@ fold_addr_of_array_ref_difference (location_t loc, tree type, if ((TREE_CODE (base0) == ARRAY_REF && TREE_CODE (base1) == ARRAY_REF && (base_offset - = fold_addr_of_array_ref_difference (loc, type, base0, base1))) + = fold_addr_of_array_ref_difference (loc, type, base0, base1, + use_pointer_diff))) || (INDIRECT_REF_P (base0) && INDIRECT_REF_P (base1) && (base_offset - = fold_binary_loc (loc, MINUS_EXPR, type, - fold_convert (type, TREE_OPERAND (base0, 0)), - fold_convert (type, - TREE_OPERAND (base1, 0))))) + = use_pointer_diff + ? fold_binary_loc (loc, POINTER_DIFF_EXPR, type, + TREE_OPERAND (base0, 0), + TREE_OPERAND (base1, 0)) + : fold_binary_loc (loc, MINUS_EXPR, type, + fold_convert (type, + TREE_OPERAND (base0, 0)), + fold_convert (type, + TREE_OPERAND (base1, 0))))) || operand_equal_p (base0, base1, OEP_ADDRESS_OF)) { tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1)); @@ -9694,7 +9711,27 @@ fold_binary_loc (location_t loc, return NULL_TREE; + case POINTER_DIFF_EXPR: case MINUS_EXPR: + /* Fold &a[i] - &a[j] to i-j. */ + if (TREE_CODE (arg0) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF + && TREE_CODE (arg1) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 0)) == ARRAY_REF) + { + tree tem = fold_addr_of_array_ref_difference (loc, type, + TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg1, 0), + code + == POINTER_DIFF_EXPR); + if (tem) + return tem; + } + + /* Further transformations are not for pointers. */ + if (code == POINTER_DIFF_EXPR) + return NULL_TREE; + /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */ if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (op1)) @@ -9752,19 +9789,6 @@ fold_binary_loc (location_t loc, fold_convert_loc (loc, type, arg0), negate_expr (op1)); - /* Fold &a[i] - &a[j] to i-j. */ - if (TREE_CODE (arg0) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF - && TREE_CODE (arg1) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (arg1, 0)) == ARRAY_REF) - { - tree tem = fold_addr_of_array_ref_difference (loc, type, - TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0)); - if (tem) - return tem; - } - /* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the same or one. Make sure the type is not saturating and has the signedness of the stripped operands, as fold_plusminus_mult_expr will re-associate. |