[PATCH] Fix PR51030, handle p ? &p->base : 0 in phiopt

Richard Guenther rguenther@suse.de
Tue Nov 8 14:02:00 GMT 2011


This should optimize VEC_BASE that Jakub was patching by teaching
phiopt to handle some one-statement intermediate basic-blocks.

Bootstrapped and tested on x86_64-unknown-linux-gnu, any comments?

Thanks,
Richard.

2011-11-08  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/51030
	* tree-ssa-phiopt.c (jump_function_from_stmt): New function.
	(value_replacement): Use it to handle trivial non-empty
	intermediate blocks.

	* gcc.dg/tree-ssa/phi-opt-6.c: New testcase.

Index: gcc/tree-ssa-phiopt.c
===================================================================
*** gcc/tree-ssa-phiopt.c	(revision 181154)
--- gcc/tree-ssa-phiopt.c	(working copy)
*************** conditional_replacement (basic_block con
*** 591,596 ****
--- 591,628 ----
    return true;
  }
  
+ /* Update *ARG which is defined in STMT so that it contains the
+    computed value if that seems profitable.  Return true if the
+    statement is made dead by that rewriting.  */
+ 
+ static bool
+ jump_function_from_stmt (tree *arg, gimple stmt)
+ {
+   enum tree_code code = gimple_assign_rhs_code (stmt);
+   if (code == ADDR_EXPR)
+     {
+       /* For arg = &p->i transform it to p, if possible.  */
+       tree rhs1 = gimple_assign_rhs1 (stmt);
+       HOST_WIDE_INT offset;
+       tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0),
+ 						&offset);
+       if (tem
+ 	  && TREE_CODE (tem) == MEM_REF
+ 	  && double_int_zero_p
+ 	       (double_int_add (mem_ref_offset (tem),
+ 				shwi_to_double_int (offset))))
+ 	{
+ 	  *arg = TREE_OPERAND (tem, 0);
+ 	  return true;
+ 	}
+     }
+   /* TODO: Much like IPA-CP jump-functions we want to handle constant
+      additions symbolically here, and we'd need to update the comparison
+      code that compares the arg + cst tuples in our caller.  For now the
+      code above exactly handles the VEC_BASE pattern from vec.h.  */
+   return false;
+ }
+ 
  /*  The function value_replacement does the main work of doing the value
      replacement.  Return true if the replacement is done.  Otherwise return
      false.
*************** value_replacement (basic_block cond_bb,
*** 602,607 ****
--- 634,640 ----
  		   edge e0, edge e1, gimple phi,
  		   tree arg0, tree arg1)
  {
+   gimple_stmt_iterator gsi;
    gimple cond;
    edge true_edge, false_edge;
    enum tree_code code;
*************** value_replacement (basic_block cond_bb,
*** 611,618 ****
    if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
      return false;
  
!   if (!empty_block_p (middle_bb))
!     return false;
  
    cond = last_stmt (cond_bb);
    code = gimple_cond_code (cond);
--- 644,675 ----
    if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
      return false;
  
!   /* Allow a single statement in MIDDLE_BB that defines one of the PHI
!      arguments.  */
!   gsi = gsi_after_labels (middle_bb);
!   if (!gsi_end_p (gsi))
!     {
!       if (is_gimple_debug (gsi_stmt (gsi)))
! 	gsi_next_nondebug (&gsi);
!       if (!gsi_end_p (gsi))
! 	{
! 	  gimple stmt = gsi_stmt (gsi);
! 	  tree lhs;
! 	  gsi_next_nondebug (&gsi);
! 	  if (!gsi_end_p (gsi))
! 	    return false;
! 	  if (!is_gimple_assign (stmt))
! 	    return false;
! 	  /* Now try to adjust arg0 or arg1 according to the computation
! 	     in the single statement.  */
! 	  lhs = gimple_assign_lhs (stmt);
! 	  if (!((lhs == arg0
! 		 && jump_function_from_stmt (&arg0, stmt))
! 		|| (lhs == arg1
! 		    && jump_function_from_stmt (&arg1, stmt))))
! 	    return false;
! 	}
!     }
  
    cond = last_stmt (cond_bb);
    code = gimple_cond_code (cond);
Index: gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c	(revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c	(revision 0)
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-phiopt1" } */
+ 
+ struct C { int i; };
+ int *g(struct C *p)
+ {
+   if (p)
+     return &p->i;
+   return (int *)0;
+ }
+ 
+ /* { dg-final { scan-tree-dump-not "if" "phiopt1" } } */
+ /* { dg-final { cleanup-tree-dump "phiopt1" } } */



More information about the Gcc-patches mailing list