[PATCH] Fix remainder of PR58742

Richard Biener rguenther@suse.de
Wed Jan 29 14:42:00 GMT 2014


This fixes the rest, adding p + (q - p) pattern matching and
(p + o1) + o2 associating (similar to the fold-const code).

And it adds testcases for the whole series.

Bootstrapped and tested on x86_64-unknown-linux-gnu and applied.

Richard.

2014-01-29  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/58742
	* tree-ssa-forwprop.c (associate_pointerplus): Rename to
	associate_pointerplus_align.
	(associate_pointerplus_diff): New function.
	(associate_pointerplus): Likewise.  Call associate_pointerplus_align
	and associate_pointerplus_diff.

	* gcc.dg/pr58742-1.c: New testcase.
	* gcc.dg/pr58742-2.c: Likewise.
	* gcc.dg/pr58742-3.c: Likewise.

Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c	(revision 207234)
--- gcc/tree-ssa-forwprop.c	(working copy)
*************** out:
*** 2802,2808 ****
     true if anything changed, false otherwise.  */
  
  static bool
! associate_pointerplus (gimple_stmt_iterator *gsi)
  {
    gimple stmt = gsi_stmt (*gsi);
    gimple def_stmt;
--- 2802,2808 ----
     true if anything changed, false otherwise.  */
  
  static bool
! associate_pointerplus_align (gimple_stmt_iterator *gsi)
  {
    gimple stmt = gsi_stmt (*gsi);
    gimple def_stmt;
*************** associate_pointerplus (gimple_stmt_itera
*** 2848,2853 ****
--- 2848,2950 ----
    update_stmt (stmt);
  
    return true;
+ }
+ 
+ /* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
+    true if anything changed, false otherwise.  */
+ 
+ static bool
+ associate_pointerplus_diff (gimple_stmt_iterator *gsi)
+ {
+   gimple stmt = gsi_stmt (*gsi);
+   gimple def_stmt;
+   tree ptr1, rhs;
+ 
+   /* Pattern match
+        tem1 = (long) ptr1;
+        tem2 = (long) ptr2;
+        tem3 = tem2 - tem1;
+        tem4 = (unsigned long) tem3;
+        tem5 = ptr1 + tem4;
+      and produce
+        tem5 = ptr2;  */
+   ptr1 = gimple_assign_rhs1 (stmt);
+   rhs = gimple_assign_rhs2 (stmt);
+   if (TREE_CODE (rhs) != SSA_NAME)
+     return false;
+   gimple minus = SSA_NAME_DEF_STMT (rhs);
+   /* Conditionally look through a sign-changing conversion.  */
+   if (is_gimple_assign (minus)
+       && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (minus))
+       && (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (minus)))
+ 	  == TYPE_PRECISION (TREE_TYPE (rhs)))
+       && TREE_CODE (gimple_assign_rhs1 (minus)) == SSA_NAME)
+     minus = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (minus));
+   if (!is_gimple_assign (minus))
+     return false;
+   if (gimple_assign_rhs_code (minus) != MINUS_EXPR)
+     return false;
+   rhs = gimple_assign_rhs2 (minus);
+   if (TREE_CODE (rhs) != SSA_NAME)
+     return false;
+   def_stmt = SSA_NAME_DEF_STMT (rhs);
+   if (!is_gimple_assign (def_stmt)
+       || ! CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
+       || gimple_assign_rhs1 (def_stmt) != ptr1)
+     return false;
+   rhs = gimple_assign_rhs1 (minus);
+   if (TREE_CODE (rhs) != SSA_NAME)
+     return false;
+   def_stmt = SSA_NAME_DEF_STMT (rhs);
+   if (!is_gimple_assign (def_stmt)
+       || ! CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+     return false;
+   rhs = gimple_assign_rhs1 (def_stmt);
+   if (! useless_type_conversion_p (TREE_TYPE (ptr1), TREE_TYPE (rhs)))
+     return false;
+ 
+   gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (rhs), rhs, NULL_TREE);
+   update_stmt (stmt);
+ 
+   return true;
+ }
+ 
+ /* Associate operands of a POINTER_PLUS_EXPR assignmen at *GSI.  Returns
+    true if anything changed, false otherwise.  */
+ 
+ static bool
+ associate_pointerplus (gimple_stmt_iterator *gsi)
+ {
+   gimple stmt = gsi_stmt (*gsi);
+   gimple def_stmt;
+   tree ptr, off1, off2;
+ 
+   if (associate_pointerplus_align (gsi)
+       || associate_pointerplus_diff (gsi))
+     return true;
+ 
+   /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
+   ptr = gimple_assign_rhs1 (stmt);
+   off1 = gimple_assign_rhs2 (stmt);
+   if (TREE_CODE (ptr) != SSA_NAME)
+     return false;
+   def_stmt = SSA_NAME_DEF_STMT (ptr);
+   if (!is_gimple_assign (def_stmt)
+       || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
+     return false;
+   ptr = gimple_assign_rhs1 (def_stmt);
+   off2 = gimple_assign_rhs2 (def_stmt);
+   if (!types_compatible_p (TREE_TYPE (off1), TREE_TYPE (off2)))
+     return false;
+ 
+   tree off = make_ssa_name (TREE_TYPE (off1), NULL);
+   gimple ostmt = gimple_build_assign_with_ops (PLUS_EXPR, off, off1, off2);
+   gsi_insert_before (gsi, ostmt, GSI_SAME_STMT);
+ 
+   gimple_assign_set_rhs_with_ops (gsi, POINTER_PLUS_EXPR, ptr, off);
+   update_stmt (stmt);
+ 
+   return true;
  }
  
  /* Combine two conversions in a row for the second conversion at *GSI.
Index: gcc/testsuite/gcc.dg/pr58742-1.c
===================================================================
*** gcc/testsuite/gcc.dg/pr58742-1.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr58742-1.c	(working copy)
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-cddce1" } */
+ 
+ int *
+ fx (int *b, int *e)
+ {
+   __SIZE_TYPE__ p = e - b;
+   /* The first forwprop pass should optimize this to return e;  */
+   return b + p;
+ }
+ 
+ /* { dg-final { scan-tree-dump "return e" "cddce1" } } */
+ /* { dg-final { cleanup-tree-dump "cddce1" } } */
Index: gcc/testsuite/gcc.dg/pr58742-2.c
===================================================================
*** gcc/testsuite/gcc.dg/pr58742-2.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr58742-2.c	(working copy)
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-cddce1" } */
+ 
+ __SIZE_TYPE__
+ fx (char *a, __SIZE_TYPE__ sz)
+ {
+   char *b = a + sz;
+   /* The first forwprop pass should optimize this to return sz;  */
+   return b - a;
+ }
+ 
+ /* { dg-final { scan-tree-dump "return sz" "cddce1" } } */
+ /* { dg-final { cleanup-tree-dump "cddce1" } } */
Index: gcc/testsuite/gcc.dg/pr58742-3.c
===================================================================
*** gcc/testsuite/gcc.dg/pr58742-3.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr58742-3.c	(working copy)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-cddce1" } */
+ 
+ int *
+ fx (int *a, int sz)
+ {
+   int *b = a + sz;
+   b = b - sz;
+   /* forwprop together with FRE should optimize this to return a;  */
+   return b;
+ }
+ 
+ /* { dg-final { scan-tree-dump "return a" "cddce1" } } */
+ /* { dg-final { cleanup-tree-dump "cddce1" } } */



More information about the Gcc-patches mailing list