diff gcc/tree-ssa-phiprop.c @ 67:f6334be47118

update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Mar 2011 17:18:12 +0900
parents b7f97abdc517
children 04ced10e8804
line wrap: on
line diff
--- a/gcc/tree-ssa-phiprop.c	Tue May 25 18:58:51 2010 +0900
+++ b/gcc/tree-ssa-phiprop.c	Tue Mar 22 17:18:12 2011 +0900
@@ -26,7 +26,6 @@
 #include "tm_p.h"
 #include "basic-block.h"
 #include "timevar.h"
-#include "diagnostic.h"
 #include "tree-pretty-print.h"
 #include "gimple-pretty-print.h"
 #include "tree-flow.h"
@@ -140,7 +139,7 @@
   edge e;
 
   gcc_assert (is_gimple_assign (use_stmt)
-	      && gimple_assign_rhs_code (use_stmt) == INDIRECT_REF);
+	      && gimple_assign_rhs_code (use_stmt) == MEM_REF);
 
   /* Build a new PHI node to replace the definition of
      the indirect reference lhs.  */
@@ -188,10 +187,17 @@
 	}
       else
 	{
+	  tree rhs = gimple_assign_rhs1 (use_stmt);
 	  gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
-	  old_arg = TREE_OPERAND (old_arg, 0);
-	  new_var = create_tmp_reg (TREE_TYPE (old_arg), NULL);
-	  tmp = gimple_build_assign (new_var, unshare_expr (old_arg));
+	  new_var = create_tmp_reg (TREE_TYPE (rhs), NULL);
+	  if (!is_gimple_min_invariant (old_arg))
+	    old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
+	  else
+	    old_arg = unshare_expr (old_arg);
+	  tmp = gimple_build_assign (new_var,
+				     fold_build2 (MEM_REF, TREE_TYPE (rhs),
+						  old_arg,
+						  TREE_OPERAND (rhs, 1)));
 	  gcc_assert (is_gimple_reg (new_var));
 	  add_referenced_var (new_var);
 	  new_var = make_ssa_name (new_var, tmp);
@@ -247,6 +253,8 @@
   use_operand_p arg_p, use;
   ssa_op_iter i;
   bool phi_inserted;
+  tree type = NULL_TREE;
+  bool one_invariant = false;
 
   if (!POINTER_TYPE_P (TREE_TYPE (ptr))
       || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
@@ -269,16 +277,29 @@
 	    return false;
 	  arg = gimple_assign_rhs1 (def_stmt);
 	}
-      if ((TREE_CODE (arg) != ADDR_EXPR
-	   /* Avoid to have to decay *&a to a[0] later.  */
-	   || !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (arg, 0))))
+      if (TREE_CODE (arg) != ADDR_EXPR
 	  && !(TREE_CODE (arg) == SSA_NAME
 	       && SSA_NAME_VERSION (arg) < n
 	       && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE
+	       && (!type
+		   || types_compatible_p
+		       (type, TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value)))
 	       && phivn_valid_p (phivn, arg, bb)))
 	return false;
+      if (!type
+	  && TREE_CODE (arg) == SSA_NAME)
+	type = TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value);
+      if (TREE_CODE (arg) == ADDR_EXPR
+	  && is_gimple_min_invariant (arg))
+	one_invariant = true;
     }
 
+  /* If we neither have an address of a decl nor can reuse a previously
+     inserted load, do not hoist anything.  */
+  if (!one_invariant
+      && !type)
+    return false;
+
   /* Find a dereferencing use.  First follow (single use) ssa
      copy chains for ptr.  */
   while (single_imm_use (ptr, &use, &use_stmt)
@@ -296,8 +317,12 @@
       /* Check whether this is a load of *ptr.  */
       if (!(is_gimple_assign (use_stmt)
 	    && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
-	    && gimple_assign_rhs_code (use_stmt) == INDIRECT_REF
+	    && gimple_assign_rhs_code (use_stmt) == MEM_REF
 	    && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr
+	    && integer_zerop (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 1))
+	    && (!type
+		|| types_compatible_p
+		     (TREE_TYPE (gimple_assign_lhs (use_stmt)), type))
 	    /* We cannot replace a load that may throw or is volatile.  */
 	    && !stmt_can_throw_internal (use_stmt)))
 	continue;
@@ -317,6 +342,7 @@
       if (!phi_inserted)
 	{
 	  res = phiprop_insert_phi (bb, phi, use_stmt, phivn, n);
+	  type = TREE_TYPE (res);
 
 	  /* Remember the value we created for *ptr.  */
 	  phivn[SSA_NAME_VERSION (ptr)].value = res;
@@ -326,7 +352,7 @@
 	     want to delete it here we also have to delete all intermediate
 	     copies.  */
 	  gsi = gsi_for_stmt (use_stmt);
-	  gsi_remove (&gsi, false);
+	  gsi_remove (&gsi, true);
 
 	  phi_inserted = true;
 	}
@@ -366,7 +392,7 @@
   /* Walk the dominator tree in preorder.  */
   bbs = get_all_dominated_blocks (CDI_DOMINATORS,
 				  single_succ (ENTRY_BLOCK_PTR));
-  for (i = 0; VEC_iterate (basic_block, bbs, i, bb); ++i)
+  FOR_EACH_VEC_ELT (basic_block, bbs, i, bb)
     for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
       did_something |= propagate_with_phi (bb, gsi_stmt (gsi), phivn, n);