From a8fc25795155d4c4d18c8c5b099748a8178b38f6 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 22 Oct 2015 08:38:15 +0000 Subject: [PATCH] fold-const.c (fold_addr_of_array_ref_difference): Properly convert operands before folding a MINUS_EXPR. 2015-10-22 Richard Biener * fold-const.c (fold_addr_of_array_ref_difference): Properly convert operands before folding a MINUS_EXPR. (fold_binary_loc): Move simplification of MINUS_EXPR on converted POINTER_PLUS_EXPRs ... * match.pd: ... here. c/ * c-typeck.c (c_finish_omp_clauses): Properly convert operands before folding a MINUS_EXPR. cp/ * semantics.c (cp_finish_omp_clause_depend_sink): Properly convert before folding a MINUS_EXPR. (finish_omp_clauses): Likewise. From-SVN: r229167 --- gcc/ChangeLog | 8 +++++++ gcc/c/ChangeLog | 5 +++++ gcc/c/c-typeck.c | 8 +++++-- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/semantics.c | 13 ++++++++---- gcc/fold-const.c | 50 +++++--------------------------------------- gcc/match.pd | 52 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 90 insertions(+), 52 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ec877a9256..63319ad6ed5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-10-22 Richard Biener + + * fold-const.c (fold_addr_of_array_ref_difference): Properly + convert operands before folding a MINUS_EXPR. + (fold_binary_loc): Move simplification of MINUS_EXPR on + converted POINTER_PLUS_EXPRs ... + * match.pd: ... here. + 2015-10-22 Richard Sandiford * builtins.c (fold_builtin_tan): Delete. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index b5179a3a714..aed7a627932 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2015-10-22 Richard Biener + + * c-typeck.c (c_finish_omp_clauses): Properly convert operands + before folding a MINUS_EXPR. + 2015-10-21 Marek Polacek PR c/68024 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 6b32781c03b..61c5313c25b 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -12547,7 +12547,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd) s = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, OMP_CLAUSE_DECL (c), s); s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, - sizetype, s, OMP_CLAUSE_DECL (c)); + sizetype, fold_convert (sizetype, s), + fold_convert + (sizetype, OMP_CLAUSE_DECL (c))); if (s == error_mark_node) s = size_one_node; OMP_CLAUSE_LINEAR_STEP (c) = s; @@ -12671,7 +12673,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd) neg ? MINUS_EXPR : PLUS_EXPR, decl, offset); t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, - sizetype, t2, decl); + sizetype, + fold_convert (sizetype, t2), + fold_convert (sizetype, decl)); if (t2 == error_mark_node) { remove = true; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0ed4e29615d..8dbff11574c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2015-10-22 Richard Biener + + * semantics.c (cp_finish_omp_clause_depend_sink): Properly convert + before folding a MINUS_EXPR. + (finish_omp_clauses): Likewise. + 2015-10-21 Paolo Carlini PR c++/66781 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c0a8b322767..11315d90668 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5632,8 +5632,9 @@ cp_finish_omp_clause_depend_sink (tree sink_clause) neg ? MINUS_EXPR : PLUS_EXPR, decl, offset); t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause), - MINUS_EXPR, sizetype, t2, - decl); + MINUS_EXPR, sizetype, + fold_convert (sizetype, t2), + fold_convert (sizetype, decl)); if (t2 == error_mark_node) return true; TREE_PURPOSE (t) = t2; @@ -5783,7 +5784,9 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd) t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, d, t); t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), - MINUS_EXPR, sizetype, t, d); + MINUS_EXPR, sizetype, + fold_convert (sizetype, t), + fold_convert (sizetype, d)); if (t == error_mark_node) { remove = true; @@ -5804,7 +5807,9 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd) t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, d, t); t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), - MINUS_EXPR, sizetype, t, d); + MINUS_EXPR, sizetype, + fold_convert (sizetype, t), + fold_convert (sizetype, d)); if (t == error_mark_node) { remove = true; diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 602ea240cb4..c4be017c50c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8841,9 +8841,11 @@ fold_addr_of_array_ref_difference (location_t loc, tree type, = fold_addr_of_array_ref_difference (loc, type, base0, base1))) || (INDIRECT_REF_P (base0) && INDIRECT_REF_P (base1) - && (base_offset = fold_binary_loc (loc, MINUS_EXPR, type, - TREE_OPERAND (base0, 0), - TREE_OPERAND (base1, 0)))) + && (base_offset + = 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)); @@ -9637,48 +9639,6 @@ fold_binary_loc (location_t loc, return NULL_TREE; case MINUS_EXPR: - /* Pointer simplifications for subtraction, simple reassociations. */ - if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0))) - { - /* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */ - if (TREE_CODE (arg0) == POINTER_PLUS_EXPR - && TREE_CODE (arg1) == POINTER_PLUS_EXPR) - { - tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); - tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1)); - tree arg10 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0)); - tree arg11 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1)); - return fold_build2_loc (loc, PLUS_EXPR, type, - fold_build2_loc (loc, MINUS_EXPR, type, - arg00, arg10), - fold_build2_loc (loc, MINUS_EXPR, type, - arg01, arg11)); - } - /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */ - else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR) - { - tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); - tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1)); - tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, arg00, - fold_convert_loc (loc, type, arg1)); - if (tmp) - return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01); - } - /* PTR0 - (PTR1 p+ A) -> (PTR0 - PTR1) - A, assuming PTR0 - PTR1 - simplifies. */ - else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR) - { - tree arg10 = fold_convert_loc (loc, type, - TREE_OPERAND (arg1, 0)); - tree arg11 = fold_convert_loc (loc, type, - TREE_OPERAND (arg1, 1)); - tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, - fold_convert_loc (loc, type, arg0), - arg10); - if (tmp) - return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11); - } - } /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */ if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1) diff --git a/gcc/match.pd b/gcc/match.pd index 1ba43c44c16..b399786bac2 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1056,7 +1056,57 @@ along with GCC; see the file COPYING3. If not see || (POINTER_TYPE_P (TREE_TYPE (@0)) && TREE_CODE (@1) == INTEGER_CST && tree_int_cst_sign_bit (@1) == 0)) - (convert @1)))))) + (convert @1)))) + + /* (T)P - (T)(P + A) -> -(T) A */ + (for add (plus pointer_plus) + (simplify + (minus (convert @0) + (convert (add @0 @1))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) + /* For integer types, if A has a smaller type + than T the result depends on the possible + overflow in P + A. + E.g. T=size_t, A=(unsigned)429497295, P>0. + However, if an overflow in P + A would cause + undefined behavior, we can assume that there + is no overflow. */ + || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + /* For pointer types, if the conversion of A to the + final type requires a sign- or zero-extension, + then we have to punt - it is not defined which + one is correct. */ + || (POINTER_TYPE_P (TREE_TYPE (@0)) + && TREE_CODE (@1) == INTEGER_CST + && tree_int_cst_sign_bit (@1) == 0)) + (negate (convert @1))))) + + /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */ + (for add (plus pointer_plus) + (simplify + (minus (convert (add @0 @1)) + (convert (add @0 @2))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) + /* For integer types, if A has a smaller type + than T the result depends on the possible + overflow in P + A. + E.g. T=size_t, A=(unsigned)429497295, P>0. + However, if an overflow in P + A would cause + undefined behavior, we can assume that there + is no overflow. */ + || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + /* For pointer types, if the conversion of A to the + final type requires a sign- or zero-extension, + then we have to punt - it is not defined which + one is correct. */ + || (POINTER_TYPE_P (TREE_TYPE (@0)) + && TREE_CODE (@1) == INTEGER_CST + && tree_int_cst_sign_bit (@1) == 0 + && TREE_CODE (@2) == INTEGER_CST + && tree_int_cst_sign_bit (@2) == 0)) + (minus (convert @1) (convert @2))))))) /* Simplifications of MIN_EXPR and MAX_EXPR. */ -- 2.30.2