diff mbox

[UPC,14/22] constant folding changes

Message ID 20151201060240.GA31253@intrepid.com
State New
Headers show

Commit Message

Gary Funck Dec. 1, 2015, 6:02 a.m. UTC
Background
----------

An overview email, describing the UPC-related changes is here:
  https://gcc.gnu.org/ml/gcc-patches/2015-12/msg00005.html

The GUPC branch is described here:
  http://gcc.gnu.org/projects/gupc.html

The UPC-related source code differences are summarized here:
  http://gccupc.org/gupc-changes

All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
bootstrapped; no test suite regressions were introduced,
relative to the GCC trunk.

If you are on the cc-list, your name was chosen either
because you are listed as a maintainer for the area that
applies to the patches described in this email, or you
were a frequent contributor of patches made to files listed
in this email.

In the change log entries included in each patch, the directory
containing the affected files is listed, followed by the files.
When the patches are applied, the change log entries will be
distributed to the appropriate ChangeLog file.

Overview
--------

UPC pointers-to-shared (aka shared pointers) are not interchangeable
with integers as they are in regular "C".  Therefore, additions
and subtraction operations which involve UPC shared pointers
should not be further simplified.

2015-11-30  Gary Funck  <gary@intrepid.com>

	gcc/
	* fold-const.c (fold_unary_loc): Do not perform this simplification
	if either of the types are UPC pointer-to-shared types.
	(fold_binary_loc): Disable optimizations involving UPC
	pointers-to-shared because integers are not interoperable
	with UPC pointers-to-shared.
	* match.pd: Do not simplify POINTER_PLUS operations which
	involve UPC pointers-to-shared.  Do not simplify integral
	conversions involving UPC pointers-to-shared.  For a chain
	of two conversions, do not simplify conversions involving
	UPC pointers-to-shared unless they meet specific criteria.

Comments

Richard Biener Dec. 1, 2015, 11:46 a.m. UTC | #1
On Mon, 30 Nov 2015, Gary Funck wrote:

> 
> Background
> ----------
> 
> An overview email, describing the UPC-related changes is here:
>   https://gcc.gnu.org/ml/gcc-patches/2015-12/msg00005.html
> 
> The GUPC branch is described here:
>   http://gcc.gnu.org/projects/gupc.html
> 
> The UPC-related source code differences are summarized here:
>   http://gccupc.org/gupc-changes
> 
> All languages (c, c++, fortran, go, lto, objc, obj-c++) have been
> bootstrapped; no test suite regressions were introduced,
> relative to the GCC trunk.
> 
> If you are on the cc-list, your name was chosen either
> because you are listed as a maintainer for the area that
> applies to the patches described in this email, or you
> were a frequent contributor of patches made to files listed
> in this email.
> 
> In the change log entries included in each patch, the directory
> containing the affected files is listed, followed by the files.
> When the patches are applied, the change log entries will be
> distributed to the appropriate ChangeLog file.
> 
> Overview
> --------
> 
> UPC pointers-to-shared (aka shared pointers) are not interchangeable
> with integers as they are in regular "C".  Therefore, additions
> and subtraction operations which involve UPC shared pointers
> should not be further simplified.

This looks worrysome.  I suppose this applies to simplifications
done before lowering only?  If so I wonder if not using regular
plus/minus/convert/nop for operations on UPC shared pointers is
better than introducing this kind of checks.

Richard.

> 2015-11-30  Gary Funck  <gary@intrepid.com>
> 
> 	gcc/
> 	* fold-const.c (fold_unary_loc): Do not perform this simplification
> 	if either of the types are UPC pointer-to-shared types.
> 	(fold_binary_loc): Disable optimizations involving UPC
> 	pointers-to-shared because integers are not interoperable
> 	with UPC pointers-to-shared.
> 	* match.pd: Do not simplify POINTER_PLUS operations which
> 	involve UPC pointers-to-shared.  Do not simplify integral
> 	conversions involving UPC pointers-to-shared.  For a chain
> 	of two conversions, do not simplify conversions involving
> 	UPC pointers-to-shared unless they meet specific criteria.
> 
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c	(.../trunk)	(revision 231059)
> +++ gcc/fold-const.c	(.../branches/gupc)	(revision 231080)
> @@ -7805,10 +7805,16 @@ fold_unary_loc (location_t loc, enum tre
>  
>        /* Convert (T1)(X p+ Y) into ((T1)X p+ Y), for pointer type, when the new
>  	 cast (T1)X will fold away.  We assume that this happens when X itself
> -	 is a cast.  */
> +	 is a cast.
> +	 
> +	 Do not perform this simplification if either of the types 
> +	 are UPC pointer-to-shared types.  */
>        if (POINTER_TYPE_P (type)
>  	  && TREE_CODE (arg0) == POINTER_PLUS_EXPR
> -	  && CONVERT_EXPR_P (TREE_OPERAND (arg0, 0)))
> +	  && CONVERT_EXPR_P (TREE_OPERAND (arg0, 0))
> +	  && !SHARED_TYPE_P (TREE_TYPE (type))
> +	  && !SHARED_TYPE_P (TREE_TYPE (
> +	                           TREE_TYPE (TREE_OPERAND (arg0, 0)))))
>  	{
>  	  tree arg00 = TREE_OPERAND (arg0, 0);
>  	  tree arg01 = TREE_OPERAND (arg0, 1);
> @@ -9271,6 +9277,14 @@ fold_binary_loc (location_t loc,
>        return NULL_TREE;
>  
>      case PLUS_EXPR:
> +      /* Disable further optimizations involving UPC shared pointers,
> +         because integers are not interoperable with shared pointers.  */
> +      if ((TREE_TYPE (arg0) && POINTER_TYPE_P (TREE_TYPE (arg0))
> +          && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))))
> +         || (TREE_TYPE (arg1) && POINTER_TYPE_P (TREE_TYPE (arg1))
> +             && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))))
> +        return NULL_TREE;
> +
>        if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
>  	{
>  	  /* X + (X / CST) * -CST is X % CST.  */
> @@ -9679,6 +9693,16 @@ fold_binary_loc (location_t loc,
>        return NULL_TREE;
>  
>      case MINUS_EXPR:
> +
> +      /* Disable further optimizations involving UPC shared pointers,
> +         because integers are not interoperable with shared pointers.
> +	 (The test below also detects pointer difference between
> +	 shared pointers, which cannot be folded.  */
> +
> +      if (TREE_TYPE (arg0) && POINTER_TYPE_P (TREE_TYPE (arg0))
> +          && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))))
> +        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)
> Index: gcc/match.pd
> ===================================================================
> --- gcc/match.pd	(.../trunk)	(revision 231059)
> +++ gcc/match.pd	(.../branches/gupc)	(revision 231080)
> @@ -931,10 +931,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>     (if (!fail && wi::bit_and (@1, zero_mask_not) == 0)
>      (inner_op @2 { wide_int_to_tree (type, cst_emit); }))))))
>  
> -/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
> -(simplify
> -  (pointer_plus (pointer_plus:s @0 @1) @3)
> -  (pointer_plus @0 (plus @1 @3)))
> +/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).
> +   (Do not apply this simplification to UPC pointers-to-shared
> +   because they are not directly convertible to integers.)  */
> +(simplify
> +  (pointer_plus (pointer_plus:s@2 @0 @1) @3)
> +  (if (!SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@2))))
> +   (pointer_plus @0 (plus @1 @3))))
>  
>  /* Pattern match
>       tem1 = (long) ptr1;
> @@ -1428,19 +1431,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>    (view_convert @0))
>  
>  /* For integral conversions with the same precision or pointer
> -   conversions use a NOP_EXPR instead.  */
> +   conversions use a NOP_EXPR instead.
> +   (Do not apply this simplification to UPC pointers-to-shared
> +   because they are not directly convertible to integers.)  */
>  (simplify
>    (view_convert @0)
> -  (if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
> -       && (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
> +  (if ((INTEGRAL_TYPE_P (type)
> +        || (POINTER_TYPE_P (type)
> +	    && !SHARED_TYPE_P (TREE_TYPE (type))))
> +       && (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +           || (POINTER_TYPE_P (TREE_TYPE (@0))
> +	       && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@0)))))
>         && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0)))
>     (convert @0)))
>  
> -/* Strip inner integral conversions that do not change precision or size.  */
> +/* Strip inner integral conversions that do not change precision or size.
> +   (Do not apply this simplification to UPC pointers-to-shared
> +   because they are not directly convertible to integers.)  */
>  (simplify
>    (view_convert (convert@0 @1))
> -  (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
> -       && (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
> +  (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +        || (POINTER_TYPE_P (TREE_TYPE (@0))
> +	    && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@0)))))
> +       && (INTEGRAL_TYPE_P (TREE_TYPE (@1))
> +           || (POINTER_TYPE_P (TREE_TYPE (@1))
> +	       && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@1)))))
>         && (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
>         && (TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1))))
>     (view_convert @1)))
> @@ -1481,6 +1496,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>        int final_vec = VECTOR_TYPE_P (type);
>        unsigned int final_prec = TYPE_PRECISION (type);
>        int final_unsignedp = TYPE_UNSIGNED (type);
> +      int final_pts = final_ptr
> +                      && SHARED_TYPE_P (TREE_TYPE (type));
> +      int inter_pts = inter_ptr
> +                      && SHARED_TYPE_P (TREE_TYPE (inter_type));
> +      int inside_pts = inside_ptr
> +                        && SHARED_TYPE_P (TREE_TYPE (inside_type));
>      }
>     (switch
>      /* In addition to the cases of two conversions in a row
> @@ -1529,7 +1550,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  	- the initial type is a pointer type and the precisions of the
>  	  intermediate and final types differ, or
>  	- the final type is a pointer type and the precisions of the
> -	  initial and intermediate types differ.  */
> +	  initial and intermediate types differ, or
> +	- the final type, intermediate type, and initial type are not either
> +	  all regular C pointer types or all UPC pointer-to-shared types, or
> +	- the final type is a UPC pointer-to-shared and the intermediate type
> +	  is a UPC-pointer-to-shared and their target types differ, or
> +	- the final type is a UPC pointer-to-shared and the intermediate type
> +	  is a UPC-pointer-to-shared and their target types differ.  */
>      (if (! inside_float && ! inter_float && ! final_float
>  	 && ! inside_vec && ! inter_vec && ! final_vec
>  	 && (inter_prec >= inside_prec || inter_prec >= final_prec)
> @@ -1541,7 +1568,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  	 && ! (inside_ptr && inter_prec != final_prec)
>  	 && ! (final_ptr && inside_prec != inter_prec)
>  	 && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
> -	       && TYPE_MODE (type) == TYPE_MODE (inter_type)))
> +	       && TYPE_MODE (type) == TYPE_MODE (inter_type))
> +	 && (final_pts == inter_pts) && (inter_pts == inside_pts)
> +	 && ! (inter_pts
> +	       && (TREE_TYPE (inter_type) != TREE_TYPE (inside_type)))
> +	 && ! (final_pts && (TREE_TYPE (type) != TREE_TYPE (inter_type))))
>       (ocvt @0))
>  
>      /* A truncation to an unsigned type (a zero-extension) should be
> 
>
Gary Funck Dec. 6, 2015, midnight UTC | #2
On 12/01/15 12:46:01, Richard Biener wrote:
> On Mon, 30 Nov 2015, Gary Funck wrote:
> > UPC pointers-to-shared (aka shared pointers) are not interchangeable
> > with integers as they are in regular "C".  Therefore, additions
> > and subtraction operations which involve UPC shared pointers
> > should not be further simplified.
> 
> This looks worrysome.  I suppose this applies to simplifications
> done before lowering only?  If so I wonder if not using regular
> plus/minus/convert/nop for operations on UPC shared pointers is
> better than introducing this kind of checks.

I suppose that is a possibility.  We could introduce
UPC_POINTER_PLUS, UPC_POINTER_CONVERT, and so-on as needed.
Just not sure how many places that for example,
UPC_POINTER_PLUS will keep showing up alongside POINTER_PLUS
and similarly UPC_POINTER_CONVERT and CONVERT.

After lowering, All UPC-specific operations have been replaced
with the GENERIC code that implements them.  We still retain
the UPC pointer-to-shared types in the tree, rather than
lowering everything to the internal representation of the
pointer-to-shared type.  I recall trying to replace
pointers-to-shared with their internal representation and
ran into some issues.  I think one of them is that procedures
accepting pointers-to-shared as parameters would have
an apparent type mis-match. It might have impacted debug info.
generation as well.  Just don't recall.

- Gary
diff mbox

Patch

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(.../trunk)	(revision 231059)
+++ gcc/fold-const.c	(.../branches/gupc)	(revision 231080)
@@ -7805,10 +7805,16 @@  fold_unary_loc (location_t loc, enum tre
 
       /* Convert (T1)(X p+ Y) into ((T1)X p+ Y), for pointer type, when the new
 	 cast (T1)X will fold away.  We assume that this happens when X itself
-	 is a cast.  */
+	 is a cast.
+	 
+	 Do not perform this simplification if either of the types 
+	 are UPC pointer-to-shared types.  */
       if (POINTER_TYPE_P (type)
 	  && TREE_CODE (arg0) == POINTER_PLUS_EXPR
-	  && CONVERT_EXPR_P (TREE_OPERAND (arg0, 0)))
+	  && CONVERT_EXPR_P (TREE_OPERAND (arg0, 0))
+	  && !SHARED_TYPE_P (TREE_TYPE (type))
+	  && !SHARED_TYPE_P (TREE_TYPE (
+	                           TREE_TYPE (TREE_OPERAND (arg0, 0)))))
 	{
 	  tree arg00 = TREE_OPERAND (arg0, 0);
 	  tree arg01 = TREE_OPERAND (arg0, 1);
@@ -9271,6 +9277,14 @@  fold_binary_loc (location_t loc,
       return NULL_TREE;
 
     case PLUS_EXPR:
+      /* Disable further optimizations involving UPC shared pointers,
+         because integers are not interoperable with shared pointers.  */
+      if ((TREE_TYPE (arg0) && POINTER_TYPE_P (TREE_TYPE (arg0))
+          && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))))
+         || (TREE_TYPE (arg1) && POINTER_TYPE_P (TREE_TYPE (arg1))
+             && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))))
+        return NULL_TREE;
+
       if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
 	{
 	  /* X + (X / CST) * -CST is X % CST.  */
@@ -9679,6 +9693,16 @@  fold_binary_loc (location_t loc,
       return NULL_TREE;
 
     case MINUS_EXPR:
+
+      /* Disable further optimizations involving UPC shared pointers,
+         because integers are not interoperable with shared pointers.
+	 (The test below also detects pointer difference between
+	 shared pointers, which cannot be folded.  */
+
+      if (TREE_TYPE (arg0) && POINTER_TYPE_P (TREE_TYPE (arg0))
+          && SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))))
+        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)
Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(.../trunk)	(revision 231059)
+++ gcc/match.pd	(.../branches/gupc)	(revision 231080)
@@ -931,10 +931,13 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (if (!fail && wi::bit_and (@1, zero_mask_not) == 0)
     (inner_op @2 { wide_int_to_tree (type, cst_emit); }))))))
 
-/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
-(simplify
-  (pointer_plus (pointer_plus:s @0 @1) @3)
-  (pointer_plus @0 (plus @1 @3)))
+/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).
+   (Do not apply this simplification to UPC pointers-to-shared
+   because they are not directly convertible to integers.)  */
+(simplify
+  (pointer_plus (pointer_plus:s@2 @0 @1) @3)
+  (if (!SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@2))))
+   (pointer_plus @0 (plus @1 @3))))
 
 /* Pattern match
      tem1 = (long) ptr1;
@@ -1428,19 +1431,31 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (view_convert @0))
 
 /* For integral conversions with the same precision or pointer
-   conversions use a NOP_EXPR instead.  */
+   conversions use a NOP_EXPR instead.
+   (Do not apply this simplification to UPC pointers-to-shared
+   because they are not directly convertible to integers.)  */
 (simplify
   (view_convert @0)
-  (if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
-       && (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
+  (if ((INTEGRAL_TYPE_P (type)
+        || (POINTER_TYPE_P (type)
+	    && !SHARED_TYPE_P (TREE_TYPE (type))))
+       && (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+           || (POINTER_TYPE_P (TREE_TYPE (@0))
+	       && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@0)))))
        && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0)))
    (convert @0)))
 
-/* Strip inner integral conversions that do not change precision or size.  */
+/* Strip inner integral conversions that do not change precision or size.
+   (Do not apply this simplification to UPC pointers-to-shared
+   because they are not directly convertible to integers.)  */
 (simplify
   (view_convert (convert@0 @1))
-  (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
-       && (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
+  (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0))
+        || (POINTER_TYPE_P (TREE_TYPE (@0))
+	    && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@0)))))
+       && (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+           || (POINTER_TYPE_P (TREE_TYPE (@1))
+	       && !SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (@1)))))
        && (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
        && (TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1))))
    (view_convert @1)))
@@ -1481,6 +1496,12 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       int final_vec = VECTOR_TYPE_P (type);
       unsigned int final_prec = TYPE_PRECISION (type);
       int final_unsignedp = TYPE_UNSIGNED (type);
+      int final_pts = final_ptr
+                      && SHARED_TYPE_P (TREE_TYPE (type));
+      int inter_pts = inter_ptr
+                      && SHARED_TYPE_P (TREE_TYPE (inter_type));
+      int inside_pts = inside_ptr
+                        && SHARED_TYPE_P (TREE_TYPE (inside_type));
     }
    (switch
     /* In addition to the cases of two conversions in a row
@@ -1529,7 +1550,13 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	- the initial type is a pointer type and the precisions of the
 	  intermediate and final types differ, or
 	- the final type is a pointer type and the precisions of the
-	  initial and intermediate types differ.  */
+	  initial and intermediate types differ, or
+	- the final type, intermediate type, and initial type are not either
+	  all regular C pointer types or all UPC pointer-to-shared types, or
+	- the final type is a UPC pointer-to-shared and the intermediate type
+	  is a UPC-pointer-to-shared and their target types differ, or
+	- the final type is a UPC pointer-to-shared and the intermediate type
+	  is a UPC-pointer-to-shared and their target types differ.  */
     (if (! inside_float && ! inter_float && ! final_float
 	 && ! inside_vec && ! inter_vec && ! final_vec
 	 && (inter_prec >= inside_prec || inter_prec >= final_prec)
@@ -1541,7 +1568,11 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	 && ! (inside_ptr && inter_prec != final_prec)
 	 && ! (final_ptr && inside_prec != inter_prec)
 	 && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
-	       && TYPE_MODE (type) == TYPE_MODE (inter_type)))
+	       && TYPE_MODE (type) == TYPE_MODE (inter_type))
+	 && (final_pts == inter_pts) && (inter_pts == inside_pts)
+	 && ! (inter_pts
+	       && (TREE_TYPE (inter_type) != TREE_TYPE (inside_type)))
+	 && ! (final_pts && (TREE_TYPE (type) != TREE_TYPE (inter_type))))
      (ocvt @0))
 
     /* A truncation to an unsigned type (a zero-extension) should be