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;

Reply via email to