[PATCH][RFC] Get back what DCE was able to do in 4.2 with V_MUST_DEFs

Richard Guenther rguenther@suse.de
Thu Sep 27 18:04:00 GMT 2007


This patch fixes the single testcase I had to XFAIL with the aggregate DSE
removal that was not added by the aggregate DSE patch.  In 4.2 DCE was
naturally able to remove some dead stores because the fact that 
V_MUST_DEFs did not have associated VUSEs made some dead stores not
necessary.

This patch re-surrects that "feature" by looking ourselves for killing
VDEFs and dealing with the fact that we still need to preserve SSA_NAME
defs for the required V_MAY_USEs the VDEFs now have.  It's less ugly
than I thought, but still all the magic with PHIs makes me wonder if
this is a good idea for stage3 (even if it fixes a regression).

So, I appreciate a look and double-check for sanity of the approach.

Bootstrap and testing is in progress (it's in stage2 now, for the
first time!) - I now have to get some beer after this ;)

Comments appreciated.  There must be a simpler way...  (yeah, fixing DSE
that is)

Thanks,
Richard.

2007-09-27  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33562
	* tree-ssa-dce.c (propagate_necessity): Look for killing
	VDEFs and do not mark their associated VMAY_USEs as necessary.
	(remove_dead_stmt): Update virtual operands of users of removed
	VDEFs.
	(eliminate_unnecessary_stmts): Do not remove unnecessary PHIs
	here,
	(perform_tree_ssa_dce): but do so here, after propagating
	necessity again.
	* tree-dfa.c (get_ref_base_and_extent): Do not ICE on things
	we cannot handle.  We return the full ref as base in that
	case.

	* gcc.c-torture/compile/20070927-1.c: New testcase.
	* gcc.dg/tree-ssa/complex-4.c: Remove XFAIL again.

Index: tree-ssa-dce.c
===================================================================
*** tree-ssa-dce.c	(revision 128815)
--- tree-ssa-dce.c	(working copy)
*************** propagate_necessity (struct edge_list *e
*** 516,523 ****
  	     links).  */
  	  ssa_op_iter iter;
  	  tree use;
  
! 	  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES)
  	    mark_operand_necessary (use);
  	}
      }
--- 516,570 ----
  	     links).  */
  	  ssa_op_iter iter;
  	  tree use;
+ 	  def_operand_p def_p;
+ 	  vuse_vec_p usevect;
+ 	  int scan = SSA_OP_ALL_USES;
+ 
+ 	  if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ 	      && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) != CALL_EXPR
+ 	      && TYPE_SIZE (TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0))))
+ 	    {
+ 	      /* If we can find a single killing VDEF, then we can avoid
+ 		 marking defs of VMAYUSEs of this store necessary.  */
+ 	      FOR_EACH_SSA_VDEF_OPERAND (def_p, usevect, stmt, iter)
+ 		{
+ 		  tree def = SSA_NAME_VAR (DEF_FROM_PTR (def_p));
+ 		  tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ 
+ 		  /* We cannot deal with multiple VMAYUSEs at stmt deletion
+ 		     time.  Also watch out to not not mark PHI nodes unless
+ 		     we know stmt is dead (which we do not here).  */
+ 		  if (VUSE_VECT_NUM_ELEM (*usevect) != 1
+ 		      || TREE_CODE (SSA_NAME_DEF_STMT
+ 			   (VUSE_ELEMENT_VAR (*usevect, 0))) == PHI_NODE)
+ 		    {
+ 		      scan |= SSA_OP_VMAYUSE;
+ 		      break;
+ 		    }
+ 
+ 		  /* If the VDEF is a structure field tag then the store
+ 		     is a kill if the SFT matches the access on the lhs.  */
+ 		  if (TREE_CODE (def) == STRUCT_FIELD_TAG)
+ 		    {
+ 		      HOST_WIDE_INT offset, size, maxsize;
+ 		      tree base = get_ref_base_and_extent (lhs, &offset,
+ 							   &size, &maxsize);
+ 		      if (size == maxsize
+ 			  && SFT_OFFSET (def) == (unsigned HOST_WIDE_INT)offset
+ 			  && SFT_SIZE (def) == (unsigned HOST_WIDE_INT)size
+ 			  && operand_equal_p (SFT_PARENT_VAR (def), base, 0))
+ 		        scan &= ~SSA_OP_VMAYUSE;
+ 		    }
  
! 		  /* If the VDEF is not a memory tag then the store is
! 		     a kill, if the lhs is the VDEF variable.  */
! 		  if (!MTAG_P (def)
! 		      && operand_equal_p (lhs, def, 0))
! 		    scan &= ~SSA_OP_VMAYUSE;
! 		}
! 	    }
! 
! 	  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, scan)
  	    mark_operand_necessary (use);
  	}
      }
*************** remove_dead_phis (basic_block bb)
*** 570,575 ****
--- 617,625 ----
  static void
  remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
  {
+   ssa_op_iter iter;
+   vuse_vec_p usevect;
+   def_operand_p def_p;
    tree t = bsi_stmt (*i);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
*************** remove_dead_stmt (block_stmt_iterator *i
*** 648,654 ****
            remove_edge (EDGE_SUCC (bb, 1));
  	}
      }
!   
    bsi_remove (i, true);  
    release_defs (t); 
  }
--- 698,735 ----
            remove_edge (EDGE_SUCC (bb, 1));
  	}
      }
! 
!   /* Update uses of VDEFs in t.  */
!   FOR_EACH_SSA_VDEF_OPERAND (def_p, usevect, t, iter)
!     {
!       imm_use_iterator iter2;
!       use_operand_p use_p;
!       tree stmt, use;
! 
!       gcc_assert (VUSE_VECT_NUM_ELEM (*usevect) == 1);
! 
!       use = VUSE_ELEMENT_VAR (*usevect, 0);
! 
!       /* If we are messing with a use defined in a loop PHI, make us
! 	 propagate the default def instead.  */
!       FOR_EACH_IMM_USE_FAST (use_p, iter2, DEF_FROM_PTR (def_p))
! 	if (TREE_CODE (USE_STMT (use_p)) == PHI_NODE
! 	    && PHI_RESULT_TREE (USE_STMT (use_p)) == use)
! 	  {
! 	    use = gimple_default_def (cfun, SSA_NAME_VAR (use));
! 	    break;
! 	  }
! 
!       /* If the use we propagate is defined in a PHI then mark
! 	 that necessary.  */
!       if (TREE_CODE (SSA_NAME_DEF_STMT (use)) == PHI_NODE)
! 	mark_stmt_necessary (SSA_NAME_DEF_STMT (use), true);
! 
!       FOR_EACH_IMM_USE_STMT (stmt, iter2, DEF_FROM_PTR (def_p))
! 	FOR_EACH_IMM_USE_ON_STMT (use_p, iter2)
! 	  SET_USE (use_p, use);
!     }
! 
    bsi_remove (i, true);  
    release_defs (t); 
  }
*************** eliminate_unnecessary_stmts (void)
*** 668,678 ****
      fprintf (dump_file, "\nEliminating unnecessary statements:\n");
  
    clear_special_calls ();
-   FOR_EACH_BB (bb)
-     {
-       /* Remove dead PHI nodes.  */
-       something_changed |= remove_dead_phis (bb);
-     }
  
    FOR_EACH_BB (bb)
      {
--- 749,754 ----
*************** perform_tree_ssa_dce (bool aggressive)
*** 820,825 ****
--- 896,902 ----
  {
    struct edge_list *el = NULL;
    bool something_changed = 0;
+   basic_block bb;
  
    tree_dce_init (aggressive);
  
*************** perform_tree_ssa_dce (bool aggressive)
*** 843,848 ****
--- 920,936 ----
    propagate_necessity (el);
  
    something_changed |= eliminate_unnecessary_stmts ();
+ 
+   /* More PHIs may have become necessary during stmt removal.  */
+   if (something_changed)
+     propagate_necessity (el);
+ 
+   FOR_EACH_BB (bb)
+     {
+       /* Remove dead PHI nodes.  */
+       something_changed |= remove_dead_phis (bb);
+     }
+ 
    something_changed |= cfg_altered;
  
    /* We do not update postdominators, so free them unconditionally.  */
Index: tree-dfa.c
===================================================================
*** tree-dfa.c	(revision 128815)
--- tree-dfa.c	(working copy)
*************** get_ref_base_and_extent (tree exp, HOST_
*** 881,888 ****
    HOST_WIDE_INT bit_offset = 0;
    bool seen_variable_array_ref = false;
  
-   gcc_assert (!SSA_VAR_P (exp));
- 
    /* First get the final access size from just the outermost expression.  */
    if (TREE_CODE (exp) == COMPONENT_REF)
      size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
--- 881,886 ----
Index: testsuite/gcc.c-torture/compile/20070927-1.c
===================================================================
*** testsuite/gcc.c-torture/compile/20070927-1.c	(revision 0)
--- testsuite/gcc.c-torture/compile/20070927-1.c	(revision 0)
***************
*** 0 ****
--- 1,33 ----
+ typedef unsigned int UDItype __attribute__ ((mode (DI)));
+ typedef UDItype UINT64;
+ typedef __attribute__ ((aligned(16))) struct {
+     UINT64 w[2];
+ } UINT128;
+ typedef __attribute__ ((aligned(16))) struct {
+     UINT64 w[4];
+ } UINT256;
+ typedef struct _DEC_DIGITS {
+     unsigned int digits;
+ } DEC_DIGITS;
+ extern DEC_DIGITS __bid_nr_digits[];
+ static void sub256 (UINT256 * pz)
+ {
+     UINT256 z;
+     *pz = z;
+ }
+ void __bid128_fma (void)
+ {
+     UINT128 C3;
+     UINT256 C4;
+     int q3;
+     int z_nr_bits;
+     int incr_exp = 0;
+     UINT64 R64;
+     UINT256 R256;
+     q3 = __bid_nr_digits[z_nr_bits].digits;
+     if (q3 <= 18)
+ 	__bid_round64_2_18 (C3.w[0], &R64);
+     R256.w[0] = C3.w[0];
+     sub256 (&R256);
+     __bid_round256_58_76 (R256, &R256);
+ }
Index: testsuite/gcc.dg/tree-ssa/complex-4.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/complex-4.c	(revision 128815)
--- testsuite/gcc.dg/tree-ssa/complex-4.c	(working copy)
*************** int f(void)
*** 10,14 ****
    return g(&t);
  }
  
! /* { dg-final { scan-tree-dump-times "__complex__" 0 "optimized" { xfail *-*-* } } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */
--- 10,14 ----
    return g(&t);
  }
  
! /* { dg-final { scan-tree-dump-times "__complex__" 0 "optimized" } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */



More information about the Gcc-patches mailing list