[PATCH][mem-ref2] Fix TER, fix into-SSA rewriting for asms

Richard Guenther rguenther@suse.de
Wed Jun 23 16:24:00 GMT 2010


With MEM_REF we now simplify

char str[9] = "1234";

void
bar (void)
{
  unsigned int temp;
  char *p = &str[2];

  memcpy (&temp, &str[1], 4);
  memcpy (p, &temp, 4);

to just

  D.2741_3 = MEM[(char * {ref-all})&str + 1B];
  MEM[(char * {ref-all})&str + 2B] = D.2741_3;

which is nice compared to

  str.0_2 = (unsigned int * {ref-all}) &str;
  D.2741_3 = str.0_2 + 1;
  temp.1_4 = *D.2741_3;
  p.2_5 = (unsigned int * {ref-all}) &str[2];
  *p.2_5 = temp.1_4;

we generate on trunk.  But that exposes a latent issue in TER in
that it will happily hand

  MEM[(char * {ref-all})&str + 2B] = MEM[(char * {ref-all})&str + 1B];

to expansion which does not handle memory overlaps in assignments well.

For the into-SSA issue I simply forgot that asms also can have
memory operands that need adjustment if we re-write a symbol into SSA 
form.

Bootstrapped and tested on x86_64-unknown-linux-gnu, gcc.dg/pr35258.c
now passes on ia64.

Richard.

2010-06-23  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-ter.c (find_replaceable_in_bb): Avoid TER if that
	creates assignments with overlap.
	* tree-ssa.c (maybe_rewrite_mem_ref_base): New function
	split out from ...
	(execute_update_addresses_taken): ... here.  Also rewrite
	MEM_REFs in asm operands.

Index: gcc/tree-ssa-ter.c
===================================================================
*** gcc/tree-ssa-ter.c	(revision 161081)
--- gcc/tree-ssa-ter.c	(working copy)
*************** find_replaceable_in_bb (temp_expr_table_
*** 616,621 ****
--- 616,639 ----
  		      }
  		  }
  
+ 	      /* If the stmt does a memory store and the replacement
+ 	         is a load aliasing it avoid creating overlapping
+ 		 assignments which we cannot expand correctly.  */
+ 	      if (gimple_vdef (stmt)
+ 		  && gimple_assign_single_p (stmt))
+ 		{
+ 		  gimple def_stmt = SSA_NAME_DEF_STMT (use);
+ 		  while (is_gimple_assign (def_stmt)
+ 			 && gimple_assign_rhs_code (def_stmt) == SSA_NAME)
+ 		    def_stmt
+ 		      = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
+ 		  if (gimple_vuse (def_stmt)
+ 		      && gimple_assign_single_p (def_stmt)
+ 		      && refs_may_alias_p (gimple_assign_lhs (stmt),
+ 					   gimple_assign_rhs1 (def_stmt)))
+ 		    same_root_var = true;
+ 		}
+ 
  	      /* Mark expression as replaceable unless stmt is volatile or the
  		 def variable has the same root variable as something in the
  		 substitution list.  */
Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c	(revision 161081)
--- gcc/tree-ssa.c	(working copy)
*************** struct gimple_opt_pass pass_early_warn_u
*** 1800,1805 ****
--- 1800,1833 ----
   }
  };
  
+ 
+ /* If necessary, rewrite the base of the reference tree *TP from
+    a MEM_REF to a plain or converted symbol.  */
+ 
+ static void
+ maybe_rewrite_mem_ref_base (tree *tp)
+ {
+   tree sym;
+ 
+   while (handled_component_p (*tp))
+     tp = &TREE_OPERAND (*tp, 0);
+   if (TREE_CODE (*tp) == MEM_REF
+       && TREE_CODE (TREE_OPERAND (*tp, 0)) == ADDR_EXPR
+       && integer_zerop (TREE_OPERAND (*tp, 1))
+       && (sym = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0))
+       && DECL_P (sym)
+       && !TREE_ADDRESSABLE (sym)
+       && symbol_marked_for_renaming (sym))
+     {
+       if (!useless_type_conversion_p (TREE_TYPE (*tp),
+ 				      TREE_TYPE (sym)))
+ 	*tp = build1 (VIEW_CONVERT_EXPR,
+ 			TREE_TYPE (*tp), sym);
+       else
+ 	*tp = sym;
+     }
+ }
+ 
  /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
  
  void
*************** execute_update_addresses_taken (bool do_
*** 1948,2021 ****
    if (update_vops)
      {
        FOR_EACH_BB (bb)
! 	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 	    {
! 	      gimple stmt = gsi_stmt (gsi);
! 
! 	      /* Re-write TARGET_MEM_REFs of symbols we want to
! 		 rewrite into SSA form.  */
! 	      if (gimple_assign_single_p (stmt))
! 		{
! 		  tree lhs = gimple_assign_lhs (stmt);
! 		  tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt);
! 		  tree sym;
! 
! 		  /* We shouldn't have any fancy wrapping of
! 		     component-refs on the LHS, but look through
! 		     VIEW_CONVERT_EXPRs as that is easy.  */
! 		  while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
! 		    lhs = TREE_OPERAND (lhs, 0);
! 		  if (TREE_CODE (lhs) == MEM_REF
! 		      && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
! 		      && integer_zerop (TREE_OPERAND (lhs, 1))
! 		      && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0))
! 		      && DECL_P (sym)
! 		      && !TREE_ADDRESSABLE (sym)
! 		      && symbol_marked_for_renaming (sym))
! 		    lhs = sym;
! 		  else
! 		    lhs = gimple_assign_lhs (stmt);
! 
! 		  /* We can have fancy wrappings on the RHS though.  */
! 		  while (handled_component_p (*rhsp))
! 		    rhsp = &TREE_OPERAND (*rhsp, 0);
! 		  if (TREE_CODE (*rhsp) == MEM_REF
! 		      && TREE_CODE (TREE_OPERAND (*rhsp, 0)) == ADDR_EXPR
! 		      && integer_zerop (TREE_OPERAND (*rhsp, 1))
! 		      && (sym = TREE_OPERAND (TREE_OPERAND (*rhsp, 0), 0))
! 		      && DECL_P (sym)
! 		      && !TREE_ADDRESSABLE (sym)
! 		      && symbol_marked_for_renaming (sym))
! 		    {
! 		      if (!useless_type_conversion_p (TREE_TYPE (*rhsp),
! 						      TREE_TYPE (sym)))
! 			*rhsp = build1 (VIEW_CONVERT_EXPR,
! 					TREE_TYPE (*rhsp), sym);
! 		      else
! 			*rhsp = sym;
! 		    }
! 
! 		  rhs = gimple_assign_rhs1 (stmt);
! 		  if (gimple_assign_lhs (stmt) != lhs
! 		      && !useless_type_conversion_p (TREE_TYPE (lhs),
! 						     TREE_TYPE (rhs)))
! 		    rhs = fold_build1 (VIEW_CONVERT_EXPR,
! 				       TREE_TYPE (lhs), rhs);
  
! 		  if (gimple_assign_lhs (stmt) != lhs)
! 		    gimple_assign_set_lhs (stmt, lhs);
  
! 		  if (gimple_assign_rhs1 (stmt) != rhs)
! 		    {
! 		      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
! 		      gimple_assign_set_rhs_from_tree (&gsi, rhs);
! 		    }
! 		}
  
! 	      if (gimple_references_memory_p (stmt)
! 		  || is_gimple_debug (stmt))
! 		update_stmt (stmt);
! 	    }
  
        /* Update SSA form here, we are called as non-pass as well.  */
        update_ssa (TODO_update_ssa);
--- 1976,2048 ----
    if (update_vops)
      {
        FOR_EACH_BB (bb)
! 	for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 	  {
! 	    gimple stmt = gsi_stmt (gsi);
  
! 	    /* Re-write TARGET_MEM_REFs of symbols we want to
! 	       rewrite into SSA form.  */
! 	    if (gimple_assign_single_p (stmt))
! 	      {
! 		tree lhs = gimple_assign_lhs (stmt);
! 		tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt);
! 		tree sym;
! 
! 		/* We shouldn't have any fancy wrapping of
! 		   component-refs on the LHS, but look through
! 		   VIEW_CONVERT_EXPRs as that is easy.  */
! 		while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
! 		  lhs = TREE_OPERAND (lhs, 0);
! 		if (TREE_CODE (lhs) == MEM_REF
! 		    && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
! 		    && integer_zerop (TREE_OPERAND (lhs, 1))
! 		    && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0))
! 		    && DECL_P (sym)
! 		    && !TREE_ADDRESSABLE (sym)
! 		    && symbol_marked_for_renaming (sym))
! 		  lhs = sym;
! 		else
! 		  lhs = gimple_assign_lhs (stmt);
! 
! 		/* Rewrite the RHS and make sure the resulting assignment
! 		   is validly typed.  */
! 		maybe_rewrite_mem_ref_base (rhsp);
! 		rhs = gimple_assign_rhs1 (stmt);
! 		if (gimple_assign_lhs (stmt) != lhs
! 		    && !useless_type_conversion_p (TREE_TYPE (lhs),
! 						   TREE_TYPE (rhs)))
! 		  rhs = fold_build1 (VIEW_CONVERT_EXPR,
! 				     TREE_TYPE (lhs), rhs);
! 
! 		if (gimple_assign_lhs (stmt) != lhs)
! 		  gimple_assign_set_lhs (stmt, lhs);
! 
! 		if (gimple_assign_rhs1 (stmt) != rhs)
! 		  {
! 		    gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
! 		    gimple_assign_set_rhs_from_tree (&gsi, rhs);
! 		  }
! 	      }
  
! 	    if (gimple_code (stmt) == GIMPLE_ASM)
! 	      {
! 		unsigned i;
! 		for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
! 		  {
! 		    tree link = gimple_asm_output_op (stmt, i);
! 		    maybe_rewrite_mem_ref_base (&TREE_VALUE (link));
! 		  }
! 		for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
! 		  {
! 		    tree link = gimple_asm_input_op (stmt, i);
! 		    maybe_rewrite_mem_ref_base (&TREE_VALUE (link));
! 		  }
! 	      }
  
! 	    if (gimple_references_memory_p (stmt)
! 		|| is_gimple_debug (stmt))
! 	      update_stmt (stmt);
! 	  }
  
        /* Update SSA form here, we are called as non-pass as well.  */
        update_ssa (TODO_update_ssa);



More information about the Gcc-patches mailing list