This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][mem-ref] Make PRE work, cleanup some stuff


This patch makes PRE work again and enables SCCVN for IDX_EXPR and
BIT_FIELD_EXPR.

Bootstrapped and "tested" on x86_64-unknown-linux-gnu, applied to
the branch.

Richard.

2008-03-09  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-operands.c (get_expr_operands): Cleanup handing of
	MEM_REF and INDIRECT_MEM_REF.
	* tree-def.c (IDX_EXPR): Fix typos.
	(BIT_FIELD_EXPR): Likewise.
	* gimple-low.c (lm_get_inner_reference): Handle large bit-field
	references with unaligned accesses.
	* tree-ssa-pre.c (phi_translate_1): Add support for IDX_EXPR,
	MEM_REF and INDIRECT_MEM_REF.
	(valid_in_sets): Likewise.
	(create_expression_by_pieces): Likewise.
	(can_value_number_operation): Likewise.  Exclude invariant
	POINTER_PLUS_EXPRs.
	(can_PRE_operation): Likewise.
	(create_value_expr_from): Add support for IDX_EXPR.
	(poolify_tree): Add support for INDIRECT_MEM_REF.
	(insert_fake_stores): Likewise.
	(gate_pre): Enable.
	* tree-ssa-loop-im.c (stmt_cost): Give IDX_EXPR the same cost
	as MULT_EXPR.
	* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle
	invariant addresses with POINTER_PLUS_EXPR.
	(visit_unary_op): Merge with visit_binary_op as visit_nary_op.
	(simplify_binary_expression): Rewrite to handle all nary
	expressions.
	(try_to_simplify): Adjust accordingly.  Add more tcc_expression
	trees as supported.
	(visit_use): Likewise.
	* tree-vn.c (vn_add): Handle IDX_EXPR.
	(vn_lookup): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-1.c: Adjust pattern.
	* gcc.dg/tree-ssa/loadpre19.c: Likewise.
	* gcc.dg/tree-ssa/loadpre22.c: Likewise.

Index: mem-ref/gcc/tree-ssa-operands.c
===================================================================
*** mem-ref.orig/gcc/tree-ssa-operands.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/tree-ssa-operands.c	2008-03-09 12:56:20.000000000 +0100
*************** get_expr_operands (tree stmt, tree *expr
*** 2152,2182 ****
        return;
  
      case MEM_REF:
-     case INDIRECT_MEM_REF:
        {
  	tree ref;
  	HOST_WIDE_INT offset, size, maxsize;
  	bool none = true;
  
  	if (TREE_THIS_VOLATILE (expr))
  	  s_ann->has_volatile_ops = true;
  
! 	if (code == MEM_REF)
! 	  add_to_addressable_set (TREE_OPERAND (expr, 0),
! 				  &s_ann->addresses_taken);
  
! 	/* This component reference becomes an access to all of the
! 	   subvariables it can touch, if we can determine that, but
! 	   *NOT* the real one.  If we can't determine which fields we
  	   could touch, the recursion will eventually get to a
  	   variable and add *all* of its subvars, or whatever is the
  	   minimum correct subset.  */
  	ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
  
! 	if (code == MEM_REF
! 	    && SSA_VAR_P (ref) && get_subvars_for_var (ref))
  	  {
- 	    subvar_t svars = get_subvars_for_var (ref);
  	    unsigned int i;
  	    tree subvar;
  
--- 2152,2180 ----
        return;
  
      case MEM_REF:
        {
  	tree ref;
  	HOST_WIDE_INT offset, size, maxsize;
  	bool none = true;
+ 	subvar_t svars;
  
  	if (TREE_THIS_VOLATILE (expr))
  	  s_ann->has_volatile_ops = true;
  
! 	add_to_addressable_set (TREE_OPERAND (expr, 0),
! 				&s_ann->addresses_taken);
  
! 	/* This memory reference becomes an access to all of the
! 	   subvariables it can touch, if it has any.
! 	   If we can't determine which fields we
  	   could touch, the recursion will eventually get to a
  	   variable and add *all* of its subvars, or whatever is the
  	   minimum correct subset.  */
  	ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
  
! 	if (SSA_VAR_P (ref)
! 	    && (svars = get_subvars_for_var (ref)))
  	  {
  	    unsigned int i;
  	    tree subvar;
  
*************** get_expr_operands (tree stmt, tree *expr
*** 2192,2216 ****
  		  }
  	      }
  
! 	    if (!none)
! 	      flags = opf_use;
  
  	    if ((DECL_P (ref) && TREE_THIS_VOLATILE (ref))
  		|| (TREE_CODE (ref) == SSA_NAME
  		    && TREE_THIS_VOLATILE (SSA_NAME_VAR (ref))))
  	      s_ann->has_volatile_ops = true;
  	  }
! 	else if (code == INDIRECT_MEM_REF)
! 	  {
! 	    get_indirect_ref_operands (stmt, expr, flags, expr, offset,
! 		                       maxsize, false);
! 	    flags = opf_use;
! 	  }
  
! 	/* Even if we found subvars above we need to ensure to see
! 	   immediate uses for d in s.a[d].  In case of s.a having
! 	   a subvar or we would miss it otherwise.  */
! 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
          get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
  
  	return;
--- 2190,2221 ----
  		  }
  	      }
  
! 	    if (none)
! 	      get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
  
  	    if ((DECL_P (ref) && TREE_THIS_VOLATILE (ref))
  		|| (TREE_CODE (ref) == SSA_NAME
  		    && TREE_THIS_VOLATILE (SSA_NAME_VAR (ref))))
  	      s_ann->has_volatile_ops = true;
  	  }
! 	else
! 	  get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
  
! 	/* See the immediate uses in the offset part.  */
!         get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
! 
! 	return;
!       }
! 
!     case INDIRECT_MEM_REF:
!       {
! 	if (TREE_THIS_VOLATILE (expr))
! 	  s_ann->has_volatile_ops = true;
! 
! 	get_addr_dereference_operands (stmt, &TREE_OPERAND (expr, 0), flags,
! 				       expr, 0, -1, true);
! 
! 	/* See the immediate uses in the offset part.  */
          get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
  
  	return;
Index: mem-ref/gcc/tree.def
===================================================================
*** mem-ref.orig/gcc/tree.def	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/tree.def	2008-03-09 12:56:20.000000000 +0100
*************** DEFTREECODE (PLUS_EXPR, "plus_expr", tcc
*** 635,641 ****
  DEFTREECODE (MINUS_EXPR, "minus_expr", tcc_binary, 2)
  DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
  
! /* Multiply-add expression with non-communtative operands.  IDX_EXPRs
     should be not re-associated, nor should its operands.
     Operand 0 is a tree for the first summand;
     Operand 1 is a tree for the first multiplicand of the second summand;
--- 635,641 ----
  DEFTREECODE (MINUS_EXPR, "minus_expr", tcc_binary, 2)
  DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
  
! /* Multiply-add expression with non-commutative operands.  IDX_EXPRs
     should be not re-associated, nor should its operands.
     Operand 0 is a tree for the first summand;
     Operand 1 is a tree for the first multiplicand of the second summand;
*************** DEFTREECODE (FDESC_EXPR, "fdesc_expr", t
*** 809,815 ****
     Operand 2 is a tree giving the constant number of bits being
     referenced which is less or equal to the precision of the value;
     Operand 3 is a tree giving the constant position of the first referenced
!    bit such that the sum of operands 2 and 3 is less or equal to the
     precision of the word.  */
  DEFTREECODE (BIT_FIELD_EXPR, "bitfield_expr", tcc_expression, 4)
  
--- 809,815 ----
     Operand 2 is a tree giving the constant number of bits being
     referenced which is less or equal to the precision of the value;
     Operand 3 is a tree giving the constant position of the first referenced
!    bit such that the sum of operands 2 and 3 is less than or equal to the
     precision of the word.  */
  DEFTREECODE (BIT_FIELD_EXPR, "bitfield_expr", tcc_expression, 4)
  
Index: mem-ref/gcc/gimple-low.c
===================================================================
*** mem-ref.orig/gcc/gimple-low.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/gimple-low.c	2008-03-09 12:56:20.000000000 +0100
*************** lm_get_inner_reference (tree exp, HOST_W
*** 852,859 ****
  	  off = off % TYPE_PRECISION (*typep);
  	  /* Then look for a type convering the whole bitfield reference.  */
  	  bf_end += off;
! 	  while (bf_end > TYPE_PRECISION (*typep))
  	    *typep = lang_hooks.types.type_for_size (2 * TYPE_PRECISION (*typep), 1);
  	}
  
        *punsignedp = DECL_UNSIGNED (TREE_OPERAND (exp, 1));
--- 852,862 ----
  	  off = off % TYPE_PRECISION (*typep);
  	  /* Then look for a type convering the whole bitfield reference.  */
  	  bf_end += off;
! 	  while (*typep && bf_end > TYPE_PRECISION (*typep))
  	    *typep = lang_hooks.types.type_for_size (2 * TYPE_PRECISION (*typep), 1);
+ 	  /* Duh, so mis-aligning it.  */
+ 	  if (!*typep)
+ 	    *typep = lang_hooks.types.type_for_mode (QImode, 1);
  	}
  
        *punsignedp = DECL_UNSIGNED (TREE_OPERAND (exp, 1));
*************** lm_get_inner_reference (tree exp, HOST_W
*** 962,968 ****
  		  tree_to_double_int (TYPE_SIZE_UNIT (*typep)));
  	        bit_offset = size_binop (PLUS_EXPR, bit_offset,
  					 double_int_to_tree (bitsizetype, bits));
! 
  		gcc_assert (!*pbitrefp);  /* ??? */
  		*pbitrefp = 1;
  	      }
--- 965,974 ----
  		  tree_to_double_int (TYPE_SIZE_UNIT (*typep)));
  	        bit_offset = size_binop (PLUS_EXPR, bit_offset,
  					 double_int_to_tree (bitsizetype, bits));
! 		while (*typep && bits.low + *pbitsize > TYPE_PRECISION (*typep))
! 		  *typep = lang_hooks.types.type_for_size (2 * TYPE_PRECISION (*typep), 1);
! 		gcc_assert (*typep);
! 		*pmode = TYPE_MODE (*typep);
  		gcc_assert (!*pbitrefp);  /* ??? */
  		*pbitrefp = 1;
  	      }
Index: mem-ref/gcc/tree-ssa-pre.c
===================================================================
*** mem-ref.orig/gcc/tree-ssa-pre.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/tree-ssa-pre.c	2008-03-09 13:21:44.000000000 +0100
*************** phi_translate_1 (tree expr, bitmap_set_t
*** 1004,1010 ****
    switch (TREE_CODE_CLASS (TREE_CODE (expr)))
      {
      case tcc_expression:
!       return NULL;
  
      case tcc_vl_exp:
        {
--- 1004,1062 ----
    switch (TREE_CODE_CLASS (TREE_CODE (expr)))
      {
      case tcc_expression:
!       if (TREE_CODE (expr) != IDX_EXPR)
! 	return NULL;
!       {
!       	tree oldop1 = TREE_OPERAND (expr, 0);
! 	tree oldval1 = oldop1;
! 	tree oldop2 = TREE_OPERAND (expr, 1);
! 	tree oldval2 = oldop2;
! 	tree oldop3 = TREE_OPERAND (expr, 2);
! 	tree oldval3 = oldop3;
! 	tree newop1;
! 	tree newop2;
! 	tree newop3;
! 	tree newexpr;
! 
! 	oldop1 = find_leader_in_sets (oldop1, set1, set2);
! 	newop1 = phi_translate_1 (oldop1, set1, set2, pred, phiblock, seen);
! 	if (newop1 == NULL)
! 	  return NULL;
! 
! 	oldop2 = find_leader_in_sets (oldop2, set1, set2);
! 	newop2 = phi_translate_1 (oldop2, set1, set2, pred, phiblock, seen);
! 	if (newop2 == NULL)
! 	  return NULL;
! 
! 	oldop3 = find_leader_in_sets (oldop3, set1, set2);
! 	newop3 = phi_translate_1 (oldop3, set1, set2, pred, phiblock, seen);
! 	if (newop3 == NULL)
! 	  return NULL;
! 
! 	if (newop1 != oldop1 || newop2 != oldop2 || newop3 != oldop3)
! 	  {
! 	    tree t;
! 	    newexpr = (tree) pool_alloc (reference_node_pool);
! 	    memcpy (newexpr, expr, tree_size (expr));
! 	    TREE_OPERAND (newexpr, 0) = newop1 == oldop1 ? oldval1 : get_value_handle (newop1);
! 	    TREE_OPERAND (newexpr, 1) = newop2 == oldop2 ? oldval2 : get_value_handle (newop2);
! 	    TREE_OPERAND (newexpr, 2) = newop3 == oldop3 ? oldval3 : get_value_handle (newop3);
! 	    t = fully_constant_expression (newexpr);
! 	    if (t != newexpr)
! 	      {
! 		pool_free (reference_node_pool, newexpr);
! 		newexpr = t;
! 	      }
! 	    else
! 	      {
! 		newexpr->base.ann = NULL;
! 		vn_lookup_or_add (newexpr);
! 	      }
! 	    expr = newexpr;
! 	  }
! 	phi_trans_add (oldexpr, expr, pred, NULL);
!       }
!       return expr;
  
      case tcc_vl_exp:
        {
*************** phi_translate_1 (tree expr, bitmap_set_t
*** 1145,1150 ****
--- 1197,1204 ----
  	VEC (tree, gc) * newvuses = NULL;
  
  	if (TREE_CODE (expr) != INDIRECT_REF
+ 	    && TREE_CODE (expr) != MEM_REF
+ 	    && TREE_CODE (expr) != INDIRECT_MEM_REF
  	    && TREE_CODE (expr) != COMPONENT_REF
  	    && TREE_CODE (expr) != ARRAY_REF)
  	  return NULL;
*************** phi_translate_1 (tree expr, bitmap_set_t
*** 1182,1187 ****
--- 1236,1251 ----
  		  return NULL;
  	      }
  	  }
+ 	else if (TREE_CODE (expr) == INDIRECT_MEM_REF
+ 	         || TREE_CODE (expr) == MEM_REF)
+ 	  {
+ 	    oldop1 = TREE_OPERAND (expr, 1);
+ 	    oldop1 = find_leader_in_sets (oldop1, set1, set2);
+ 	    newop1 = phi_translate_1 (oldop1, set1, set2, pred, phiblock, seen);
+ 
+ 	    if (newop1 == NULL)
+ 	      return NULL;
+ 	  }
  
  	oldvuses = get_expression_vuses (expr);
  	if (oldvuses)
*************** phi_translate_1 (tree expr, bitmap_set_t
*** 1206,1211 ****
--- 1270,1278 ----
  		if (newop3)
  		  TREE_OPERAND (newexpr, 3) = get_value_handle (newop3);
  	      }
+ 	    else if (TREE_CODE (expr) == MEM_REF
+ 		     || TREE_CODE (expr) == INDIRECT_MEM_REF)
+ 	      TREE_OPERAND (newexpr, 1) = get_value_handle (newop1);
  
  	    t = fully_constant_expression (newexpr);
  
*************** valid_in_sets (bitmap_set_t set1, bitmap
*** 1499,1505 ****
        }
  
      case tcc_expression:
!       return false;
  
      case tcc_vl_exp:
        {
--- 1566,1582 ----
        }
  
      case tcc_expression:
!       if (TREE_CODE (expr) != IDX_EXPR)
! 	return false;
!       {
! 	tree op1 = TREE_OPERAND (expr, 0);
! 	tree op2 = TREE_OPERAND (expr, 1);
! 	tree op3 = TREE_OPERAND (expr, 2);
! 
! 	return union_contains_value (set1, set2, op1)
! 	  && union_contains_value (set1, set2, op2)
! 	  && union_contains_value (set1, set2, op3);
!       }
  
      case tcc_vl_exp:
        {
*************** valid_in_sets (bitmap_set_t set1, bitmap
*** 1529,1534 ****
--- 1606,1613 ----
      case tcc_reference:
        {
  	if (TREE_CODE (expr) == INDIRECT_REF
+ 	    || TREE_CODE (expr) == MEM_REF
+ 	    || TREE_CODE (expr) == INDIRECT_MEM_REF
  	    || TREE_CODE (expr) == COMPONENT_REF
  	    || TREE_CODE (expr) == ARRAY_REF)
  	  {
*************** valid_in_sets (bitmap_set_t set1, bitmap
*** 1556,1562 ****
  		if (op3
  		    && !union_contains_value (set1, set2, op3))
  		  return false;
! 	    }
  	    return !value_dies_in_block_x (expr, block);
  	  }
        }
--- 1635,1650 ----
  		if (op3
  		    && !union_contains_value (set1, set2, op3))
  		  return false;
! 	      }
! 	    else if (TREE_CODE (expr) == MEM_REF
! 		     || TREE_CODE (expr) == INDIRECT_MEM_REF)
! 	      {
! 		tree op1 = TREE_OPERAND (expr, 1);
! 		gcc_assert (is_gimple_min_invariant (op1)
! 			    || TREE_CODE (op1) == VALUE_HANDLE);
! 		if (!union_contains_value (set1, set2, op1))
! 		  return false;
! 	      }
  	    return !value_dies_in_block_x (expr, block);
  	  }
        }
*************** can_value_number_operation (tree op)
*** 2088,2098 ****
  {
    return (UNARY_CLASS_P (op)
  	  && !is_exception_related (TREE_OPERAND (op, 0)))
!     || BINARY_CLASS_P (op)
      || COMPARISON_CLASS_P (op)
      || REFERENCE_CLASS_P (op)
      || (TREE_CODE (op) == CALL_EXPR
! 	&& can_value_number_call (op));
  }
  
  
--- 2176,2189 ----
  {
    return (UNARY_CLASS_P (op)
  	  && !is_exception_related (TREE_OPERAND (op, 0)))
!     || (BINARY_CLASS_P (op)
! 	&& (TREE_CODE (op) != POINTER_PLUS_EXPR
! 	    || !is_gimple_min_invariant (op)))
      || COMPARISON_CLASS_P (op)
      || REFERENCE_CLASS_P (op)
      || (TREE_CODE (op) == CALL_EXPR
! 	&& can_value_number_call (op))
!     || TREE_CODE (op) == IDX_EXPR;
  }
  
  
*************** static bool
*** 2104,2112 ****
  can_PRE_operation (tree op)
  {
    return UNARY_CLASS_P (op)
!     || BINARY_CLASS_P (op)
      || COMPARISON_CLASS_P (op)
      || TREE_CODE (op) == INDIRECT_REF
      || TREE_CODE (op) == COMPONENT_REF
      || TREE_CODE (op) == CALL_EXPR
      || TREE_CODE (op) == ARRAY_REF;
--- 2195,2208 ----
  can_PRE_operation (tree op)
  {
    return UNARY_CLASS_P (op)
!     || (BINARY_CLASS_P (op)
! 	&& (TREE_CODE (op) != POINTER_PLUS_EXPR
! 	    || !is_gimple_min_invariant (op)))
      || COMPARISON_CLASS_P (op)
+     || TREE_CODE (op) == IDX_EXPR
      || TREE_CODE (op) == INDIRECT_REF
+     || TREE_CODE (op) == INDIRECT_MEM_REF
+     || TREE_CODE (op) == MEM_REF
      || TREE_CODE (op) == COMPONENT_REF
      || TREE_CODE (op) == CALL_EXPR
      || TREE_CODE (op) == ARRAY_REF;
*************** create_expression_by_pieces (basic_block
*** 2320,2325 ****
--- 2416,2437 ----
  	  {
  	    folded = create_component_ref_by_pieces (block, expr, stmts);
  	  }
+ 	else if (TREE_CODE (expr) == INDIRECT_MEM_REF
+ 	    	 || TREE_CODE (expr) == MEM_REF)
+ 	  {
+ 	    tree op1 = TREE_OPERAND (expr, 0);
+ 	    tree op2 = TREE_OPERAND (expr, 1);
+ 	    tree genop2, genop1;
+ 	    if (TREE_CODE (expr) == INDIRECT_MEM_REF)
+ 	      genop1 = find_or_generate_expression (block, op1, stmts);
+ 	    else
+ 	      genop1 = create_component_ref_by_pieces (block, op1, stmts);
+ 	    genop2 = find_or_generate_expression (block, op2, stmts);
+ 	    folded = build_gimple_mem_ref (TREE_CODE (expr), TREE_TYPE (expr),
+ 			      		   genop1, genop2,
+ 			      		   MEM_REF_ALIAS_SET (expr),
+ 			      		   MEM_REF_ALIGN (expr));
+ 	  }
  	else
  	  {
  	    tree op1 = TREE_OPERAND (expr, 0);
*************** create_expression_by_pieces (basic_block
*** 2331,2336 ****
--- 2443,2462 ----
  	break;
        }
  
+     case tcc_expression:
+       gcc_assert (TREE_CODE (expr) == IDX_EXPR);
+       {
+       	tree op1 = TREE_OPERAND (expr, 0);
+ 	tree op2 = TREE_OPERAND (expr, 1);
+ 	tree op3 = TREE_OPERAND (expr, 2);
+ 	tree genop1 = find_or_generate_expression (block, op1, stmts);
+ 	tree genop2 = find_or_generate_expression (block, op2, stmts);
+ 	tree genop3 = find_or_generate_expression (block, op3, stmts);
+ 	folded = fold_build3 (TREE_CODE (expr), TREE_TYPE (expr),
+ 			      genop1, genop2, genop3);
+ 	break;
+       }
+ 
      case tcc_binary:
      case tcc_comparison:
        {
*************** create_value_expr_from (tree expr, basic
*** 2999,3004 ****
--- 3125,3132 ----
      pool = binary_node_pool;
    else if (TREE_CODE_CLASS (code) == tcc_comparison)
      pool = comparison_node_pool;
+   else if (code == IDX_EXPR)
+     pool = reference_node_pool;
    else
      gcc_assert (code == CALL_EXPR);
  
*************** poolify_tree (tree node)
*** 3063,3068 ****
--- 3191,3205 ----
  	return temp;
        }
        break;
+     case INDIRECT_MEM_REF:
+       {
+ 	tree temp = (tree) pool_alloc (reference_node_pool);
+ 	memcpy (temp, node, tree_size (node));
+ 	TREE_OPERAND (temp, 0) = poolify_tree (TREE_OPERAND (temp, 0));
+ 	TREE_OPERAND (temp, 1) = poolify_tree (TREE_OPERAND (temp, 1));
+ 	return temp;
+       }
+       break;
      case GIMPLE_MODIFY_STMT:
        {
  	tree temp = (tree) pool_alloc (modify_expr_node_pool);
*************** insert_fake_stores (void)
*** 3134,3140 ****
  	     virtual uses occur in abnormal phis.  */
  
  	  if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
! 	      && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == INDIRECT_REF
  	      && !AGGREGATE_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0)))
  	      && TREE_CODE (TREE_TYPE (GIMPLE_STMT_OPERAND
  					(stmt, 0))) != COMPLEX_TYPE)
--- 3271,3278 ----
  	     virtual uses occur in abnormal phis.  */
  
  	  if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
! 	      && (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == INDIRECT_REF
! 		  || TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == INDIRECT_MEM_REF)
  	      && !AGGREGATE_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0)))
  	      && TREE_CODE (TREE_TYPE (GIMPLE_STMT_OPERAND
  					(stmt, 0))) != COMPLEX_TYPE)
*************** do_pre (void)
*** 3993,4000 ****
  static bool
  gate_pre (void)
  {
!   return !(cfun->curr_properties & PROP_gimple_lmem) /* ???  MEM_REF  */
! 	 && flag_tree_pre != 0;
  }
  
  struct tree_opt_pass pass_pre =
--- 4131,4137 ----
  static bool
  gate_pre (void)
  {
!   return flag_tree_pre != 0;
  }
  
  struct tree_opt_pass pass_pre =
Index: mem-ref/gcc/tree-ssa-loop-im.c
===================================================================
*** mem-ref.orig/gcc/tree-ssa-loop-im.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/tree-ssa-loop-im.c	2008-03-09 12:56:20.000000000 +0100
*************** stmt_cost (tree stmt)
*** 470,475 ****
--- 470,476 ----
      case ROUND_MOD_EXPR:
      case TRUNC_MOD_EXPR:
      case RDIV_EXPR:
+     case IDX_EXPR:
        /* Division and multiplication are usually expensive.  */
        cost += 20;
        break;
Index: mem-ref/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-1.c
===================================================================
*** mem-ref.orig/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-1.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-1.c	2008-03-09 12:56:20.000000000 +0100
*************** int f(int *a)
*** 12,16 ****
  }
  
  /* { dg-final { scan-tree-dump "Replaced \\\(int \\\*\\\) b_.*with a_" "fre" } } */
! /* { dg-final { scan-tree-dump "Replaced \\\*c_.*with t_" "fre" } } */
  /* { dg-final { cleanup-tree-dump "fre" } } */
--- 12,16 ----
  }
  
  /* { dg-final { scan-tree-dump "Replaced \\\(int \\\*\\\) b_.*with a_" "fre" } } */
! /* { dg-final { scan-tree-dump "Replaced .*c_.*with t_" "fre" } } */
  /* { dg-final { cleanup-tree-dump "fre" } } */
Index: mem-ref/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c
===================================================================
*** mem-ref.orig/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c	2008-03-09 12:56:20.000000000 +0100
*************** int main(type *a, int argc)
*** 12,16 ****
    e = (*a)[argc];
    return e;
  }
! /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"  } } */
  /* { dg-final { cleanup-tree-dump "pre" } } */
--- 12,16 ----
    e = (*a)[argc];
    return e;
  }
! /* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"  } } */
  /* { dg-final { cleanup-tree-dump "pre" } } */
Index: mem-ref/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c
===================================================================
*** mem-ref.orig/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c	2008-03-09 12:55:50.000000000 +0100
--- mem-ref/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c	2008-03-09 12:56:20.000000000 +0100
*************** int main(type *a, int argc)
*** 15,19 ****
    return d + e;
  }
  
! /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
  /* { dg-final { cleanup-tree-dump "pre" } } */
--- 15,19 ----
    return d + e;
  }
  
! /* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
  /* { dg-final { cleanup-tree-dump "pre" } } */
Index: mem-ref/gcc/tree-ssa-sccvn.c
===================================================================
*** mem-ref.orig/gcc/tree-ssa-sccvn.c	2008-03-09 12:56:27.000000000 +0100
--- mem-ref/gcc/tree-ssa-sccvn.c	2008-03-09 12:56:33.000000000 +0100
*************** copy_reference_ops_from_ref (tree ref, V
*** 563,568 ****
--- 563,574 ----
  	case VIEW_CONVERT_EXPR:
  	case ADDR_EXPR:
  	  break;
+ 	case POINTER_PLUS_EXPR:
+ 	  /* ???  It happens that we end up with INDIRECT_MEM_REF
+ 	     of for example &"foo" + 1.  */
+ 	  gcc_assert (is_gimple_min_invariant (ref));
+ 	  temp.op0 = TREE_OPERAND (ref, 1);
+ 	  break;
  	default:
  	  gcc_unreachable ();
  
*************** visit_copy (tree lhs, tree rhs)
*** 1041,1073 ****
    return set_ssa_val_to (lhs, rhs);
  }
  
! /* Visit a unary operator RHS, value number it, and return true if the
!    value number of LHS has changed as a result.  */
! 
! static bool
! visit_unary_op (tree lhs, tree op)
! {
!   bool changed = false;
!   tree result = vn_nary_op_lookup (op);
! 
!   if (result)
!     {
!       changed = set_ssa_val_to (lhs, result);
!     }
!   else
!     {
!       changed = set_ssa_val_to (lhs, lhs);
!       vn_nary_op_insert (op, lhs);
!     }
! 
!   return changed;
! }
! 
! /* Visit a binary operator RHS, value number it, and return true if the
     value number of LHS has changed as a result.  */
  
  static bool
! visit_binary_op (tree lhs, tree op)
  {
    bool changed = false;
    tree result = vn_nary_op_lookup (op);
--- 1047,1057 ----
    return set_ssa_val_to (lhs, rhs);
  }
  
! /* Visit a nary operator RHS, value number it, and return true if the
     value number of LHS has changed as a result.  */
  
  static bool
! visit_nary_op (tree lhs, tree op)
  {
    bool changed = false;
    tree result = vn_nary_op_lookup (op);
*************** valueize_expr (tree expr)
*** 1340,1395 ****
    return expr;
  }
  
! /* Simplify the binary expression RHS, and return the result if
!    simplified. */
  
  static tree
! simplify_binary_expression (tree stmt, tree rhs)
  {
!   tree result = NULL_TREE;
!   tree op0 = TREE_OPERAND (rhs, 0);
!   tree op1 = TREE_OPERAND (rhs, 1);
  
    /* This will not catch every single case we could combine, but will
       catch those with constants.  The goal here is to simultaneously
       combine constants between expressions, but avoid infinite
       expansion of expressions during simplification.  */
!   if (TREE_CODE (op0) == SSA_NAME)
!     {
!       if (VN_INFO (op0)->has_constants)
! 	op0 = valueize_expr (VN_INFO (op0)->expr);
!       else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0)
! 	op0 = SSA_VAL (op0);
!     }
! 
!   if (TREE_CODE (op1) == SSA_NAME)
      {
!       if (VN_INFO (op1)->has_constants)
! 	op1 = valueize_expr (VN_INFO (op1)->expr);
!       else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1)
! 	op1 = SSA_VAL (op1);
      }
  
    /* Avoid folding if nothing changed.  */
!   if (op0 == TREE_OPERAND (rhs, 0)
!       && op1 == TREE_OPERAND (rhs, 1))
!     return NULL_TREE;
  
    fold_defer_overflow_warnings ();
  
!   result = fold_binary (TREE_CODE (rhs), TREE_TYPE (rhs), op0, op1);
! 
!   fold_undefer_overflow_warnings (result && valid_gimple_expression_p (result),
! 				  stmt, 0);
  
    /* Make sure result is not a complex expression consisting
       of operators of operators (IE (a + b) + (a + c))
       Otherwise, we will end up with unbounded expressions if
       fold does anything at all.  */
!   if (result && valid_gimple_expression_p (result))
      return result;
  
!   return NULL_TREE;
  }
  
  /* Simplify the unary expression RHS, and return the result if
--- 1324,1396 ----
    return expr;
  }
  
! /* Simplify the nary expression RHS, and return the result if
!    simplified.  */
  
  static tree
! simplify_nary_expression (tree stmt, tree rhs)
  {
!   tree result, op[4];
!   unsigned length = TREE_CODE_LENGTH (TREE_CODE (rhs));
!   bool changed = false;
!   unsigned i;
  
    /* This will not catch every single case we could combine, but will
       catch those with constants.  The goal here is to simultaneously
       combine constants between expressions, but avoid infinite
       expansion of expressions during simplification.  */
!   for (i = 0; i < length; ++i)
      {
!       tree tem = TREE_OPERAND (rhs, i);
!       if (TREE_CODE (tem) == SSA_NAME)
! 	{
! 	  if (VN_INFO (tem)->has_constants)
! 	    tem = valueize_expr (VN_INFO (tem)->expr);
! 	  else if (SSA_VAL (tem) != VN_TOP)
! 	    tem = SSA_VAL (tem);
! 	}
!       if (tem != TREE_OPERAND (rhs, i))
! 	changed = true;
!       op[i] = tem;
      }
  
    /* Avoid folding if nothing changed.  */
!   if (!changed)
!     return rhs;
  
    fold_defer_overflow_warnings ();
  
!   switch (length)
!     {
!     case 2:
!       result = fold_binary (TREE_CODE (rhs), TREE_TYPE (rhs),
! 			    op[0], op[1]);
!       break;
!     case 3:
!       result = fold_ternary (TREE_CODE (rhs), TREE_TYPE (rhs),
! 			     op[0], op[1], op[2]);
!       break;
!     case 4:
!       result = fold_quaternary (TREE_CODE (rhs), TREE_TYPE (rhs),
! 				op[0], op[1], op[2], op[3]);
!       break;
!     default:
!       result = NULL_TREE;
!     }
  
    /* Make sure result is not a complex expression consisting
       of operators of operators (IE (a + b) + (a + c))
       Otherwise, we will end up with unbounded expressions if
       fold does anything at all.  */
!   if (result && !valid_gimple_expression_p (result))
!     result = NULL_TREE;
! 
!   fold_undefer_overflow_warnings (result != NULL_TREE, stmt, 0);
! 
!   if (result)
      return result;
  
!   return rhs;
  }
  
  /* Simplify the unary expression RHS, and return the result if
*************** try_to_simplify (tree stmt, tree rhs)
*** 1479,1485 ****
  	  break;
  	case tcc_comparison:
  	case tcc_binary:
! 	  return simplify_binary_expression (stmt, rhs);
  	  break;
  	default:
  	  break;
--- 1480,1500 ----
  	  break;
  	case tcc_comparison:
  	case tcc_binary:
! 	  return simplify_nary_expression (stmt, rhs);
! 	  break;
! 	case tcc_expression:
! 	  if (TREE_CODE (rhs) == ADDR_EXPR
! 	      || TREE_CODE (rhs) == TRUTH_NOT_EXPR)
! 	    return simplify_unary_expression (rhs);
! 	  else if (TREE_CODE (rhs) == TRUTH_ANDIF_EXPR
! 		   || TREE_CODE (rhs) == TRUTH_ORIF_EXPR
! 		   || TREE_CODE (rhs) == TRUTH_AND_EXPR
! 		   || TREE_CODE (rhs) == TRUTH_OR_EXPR
! 		   || TREE_CODE (rhs) == TRUTH_XOR_EXPR
! 		   || TREE_CODE (rhs) == IDX_EXPR
! 		   || TREE_CODE (rhs) == COND_EXPR
! 		   || TREE_CODE (rhs) == BIT_FIELD_EXPR)
! 	    return simplify_nary_expression (stmt, rhs);
  	  break;
  	default:
  	  break;
*************** visit_use (tree use)
*** 1631,1640 ****
  		  switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
  		    {
  		    case tcc_unary:
! 		      changed = visit_unary_op (lhs, rhs);
! 		      break;
  		    case tcc_binary:
! 		      changed = visit_binary_op (lhs, rhs);
  		      break;
  		      /* If tcc_vl_expr ever encompasses more than
  			 CALL_EXPR, this will need to be changed.  */
--- 1646,1654 ----
  		  switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
  		    {
  		    case tcc_unary:
! 		    case tcc_comparison:
  		    case tcc_binary:
! 		      changed = visit_nary_op (lhs, rhs);
  		      break;
  		      /* If tcc_vl_expr ever encompasses more than
  			 CALL_EXPR, this will need to be changed.  */
*************** visit_use (tree use)
*** 1646,1657 ****
  		      break;
  		    case tcc_declaration:
  		    case tcc_reference:
  		      changed = visit_reference_op_load (lhs, rhs, stmt);
  		      break;
  		    case tcc_expression:
! 		      if (TREE_CODE (rhs) == ADDR_EXPR)
  			{
! 			  changed = visit_unary_op (lhs, rhs);
  			  goto done;
  			}
  		      /* Fallthrough.  */
--- 1660,1688 ----
  		      break;
  		    case tcc_declaration:
  		    case tcc_reference:
+ 		      if (TREE_CODE (rhs) == BIT_FIELD_REF
+ 			  || TREE_CODE (rhs) == REALPART_EXPR
+ 			  || TREE_CODE (rhs) == IMAGPART_EXPR
+ 			  || TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
+ 			{
+ 			  changed = visit_nary_op (lhs, rhs);
+ 			  goto done;
+ 			}
  		      changed = visit_reference_op_load (lhs, rhs, stmt);
  		      break;
  		    case tcc_expression:
! 		      if (TREE_CODE (rhs) == ADDR_EXPR
! 			  || TREE_CODE (rhs) == IDX_EXPR
! 			  || TREE_CODE (rhs) == BIT_FIELD_EXPR
! 			  || TREE_CODE (rhs) == COND_EXPR
! 			  || TREE_CODE (rhs) == TRUTH_ANDIF_EXPR
! 			  || TREE_CODE (rhs) == TRUTH_ORIF_EXPR
! 			  || TREE_CODE (rhs) == TRUTH_AND_EXPR
! 			  || TREE_CODE (rhs) == TRUTH_OR_EXPR
! 			  || TREE_CODE (rhs) == TRUTH_XOR_EXPR
! 			  || TREE_CODE (rhs) == TRUTH_NOT_EXPR)
  			{
! 			  changed = visit_nary_op (lhs, rhs);
  			  goto done;
  			}
  		      /* Fallthrough.  */
Index: mem-ref/gcc/tree-vn.c
===================================================================
*** mem-ref.orig/gcc/tree-vn.c	2008-03-09 12:56:27.000000000 +0100
--- mem-ref/gcc/tree-vn.c	2008-03-09 12:56:33.000000000 +0100
*************** vn_add (tree expr, tree val)
*** 199,205 ****
  	  SSA_NAME_VALUE (expr) = val;
  	  break;
  	}
!       else if (TREE_CODE (expr) == ADDR_EXPR)
  	{
  	  vn_nary_op_insert (expr, val);
  	  break;
--- 199,206 ----
  	  SSA_NAME_VALUE (expr) = val;
  	  break;
  	}
!       else if (TREE_CODE (expr) == ADDR_EXPR
! 	       || TREE_CODE (expr) == IDX_EXPR)
  	{
  	  vn_nary_op_insert (expr, val);
  	  break;
*************** vn_lookup (tree expr)
*** 267,273 ****
  	return vn_reference_lookup (expr, NULL);
        else if (TREE_CODE (expr) == SSA_NAME)
  	return SSA_NAME_VALUE (expr);
!       else if (TREE_CODE (expr) == ADDR_EXPR)
  	return vn_nary_op_lookup (expr);
        /* FALLTHROUGH */
      default:
--- 268,275 ----
  	return vn_reference_lookup (expr, NULL);
        else if (TREE_CODE (expr) == SSA_NAME)
  	return SSA_NAME_VALUE (expr);
!       else if (TREE_CODE (expr) == ADDR_EXPR
! 	       || TREE_CODE (expr) == IDX_EXPR)
  	return vn_nary_op_lookup (expr);
        /* FALLTHROUGH */
      default:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]