Bootstrapped and tested on x86_64-unknown-linux-gnu, the OMP changes were approved by Jakub on IRC.
Richard. 2015-10-22 Richard Biener <rguent...@suse.de> * 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. Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 229119) --- gcc/fold-const.c (working copy) *************** fold_addr_of_array_ref_difference (locat *** 8846,8854 **** = 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)))) || operand_equal_p (base0, base1, OEP_ADDRESS_OF)) { tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1)); --- 8864,8874 ---- = 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, ! 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)); *************** fold_binary_loc (location_t loc, *** 9642,9689 **** 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) --- 9662,9667 ---- Index: gcc/match.pd =================================================================== *** gcc/match.pd (revision 229119) --- gcc/match.pd (working copy) *************** (define_operator_list CPROJ BUILT_IN_CPR *** 978,984 **** || (POINTER_TYPE_P (TREE_TYPE (@0)) && TREE_CODE (@1) == INTEGER_CST && tree_int_cst_sign_bit (@1) == 0)) ! (convert @1)))))) /* Simplifications of MIN_EXPR and MAX_EXPR. */ --- 978,1034 ---- || (POINTER_TYPE_P (TREE_TYPE (@0)) && TREE_CODE (@1) == INTEGER_CST && tree_int_cst_sign_bit (@1) == 0)) ! (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. */ Index: gcc/c/c-typeck.c =================================================================== *** gcc/c/c-typeck.c (revision 229119) --- gcc/c/c-typeck.c (working copy) *************** c_finish_omp_clauses (tree clauses, bool *** 12519,12525 **** 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)); if (s == error_mark_node) s = size_one_node; OMP_CLAUSE_LINEAR_STEP (c) = s; --- 12519,12527 ---- 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, 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; *************** c_finish_omp_clauses (tree clauses, bool *** 12643,12649 **** neg ? MINUS_EXPR : PLUS_EXPR, decl, offset); t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, ! sizetype, t2, decl); if (t2 == error_mark_node) { remove = true; --- 12645,12653 ---- neg ? MINUS_EXPR : PLUS_EXPR, decl, offset); t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, ! sizetype, ! fold_convert (sizetype, t2), ! fold_convert (sizetype, decl)); if (t2 == error_mark_node) { remove = true; Index: gcc/cp/semantics.c =================================================================== *** gcc/cp/semantics.c (revision 229119) --- gcc/cp/semantics.c (working copy) *************** cp_finish_omp_clause_depend_sink (tree s *** 5632,5639 **** neg ? MINUS_EXPR : PLUS_EXPR, decl, offset); t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause), ! MINUS_EXPR, sizetype, t2, ! decl); if (t2 == error_mark_node) return true; TREE_PURPOSE (t) = t2; --- 5632,5640 ---- neg ? MINUS_EXPR : PLUS_EXPR, decl, offset); t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause), ! MINUS_EXPR, sizetype, ! fold_convert (sizetype, t2), ! fold_convert (sizetype, decl)); if (t2 == error_mark_node) return true; TREE_PURPOSE (t) = t2; *************** finish_omp_clauses (tree clauses, bool a *** 5783,5789 **** 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); if (t == error_mark_node) { remove = true; --- 5784,5792 ---- t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, d, t); t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), ! MINUS_EXPR, sizetype, ! fold_convert (sizetype, t), ! fold_convert (sizetype, d)); if (t == error_mark_node) { remove = true; *************** finish_omp_clauses (tree clauses, bool a *** 5804,5810 **** 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); if (t == error_mark_node) { remove = true; --- 5807,5815 ---- t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, d, t); t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), ! MINUS_EXPR, sizetype, ! fold_convert (sizetype, t), ! fold_convert (sizetype, d)); if (t == error_mark_node) { remove = true;