[PATCH][mem-ref2] Properly fold MEM_REF args during VN

Richard Guenther rguenther@suse.de
Wed Jun 16 14:48:00 GMT 2010


Which simplifies a lot compared to the old INDIRECT_REF folding code.

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

Richard.

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

	* tree-ssa-pre.c (phi_translate_1): Fold MEM_REFs.
	* tree-ssa-sccvn.c (vn_reference_fold_indirect): Adjust
	for MEM_REFs.
	(valueize_refs): Fold MEM_REFs.

Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 160825)
--- gcc/tree-ssa-pre.c	(working copy)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1634,1640 ****
  	       a preceding indirect reference.  */
  	    if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
  		&& VEC_index (vn_reference_op_s,
! 			      newoperands, j - 1)->opcode == INDIRECT_REF)
  	      vn_reference_fold_indirect (&newoperands, &j);
  	  }
  	if (i != VEC_length (vn_reference_op_s, operands))
--- 1634,1640 ----
  	       a preceding indirect reference.  */
  	    if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
  		&& VEC_index (vn_reference_op_s,
! 			      newoperands, j - 1)->opcode == MEM_REF)
  	      vn_reference_fold_indirect (&newoperands, &j);
  	  }
  	if (i != VEC_length (vn_reference_op_s, operands))
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c	(revision 160825)
--- gcc/tree-ssa-sccvn.c	(working copy)
*************** void
*** 953,1014 ****
  vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **ops,
  			    unsigned int *i_p)
  {
-   VEC(vn_reference_op_s, heap) *mem = NULL;
-   vn_reference_op_t op;
    unsigned int i = *i_p;
!   unsigned int j;
! 
!   /* Get ops for the addressed object.  */
!   op = VEC_index (vn_reference_op_s, *ops, i);
!   /* ???  If this is our usual typeof &ARRAY vs. &ARRAY[0] problem, work
!      around it to avoid later ICEs.  */
!   if (TREE_CODE (TREE_TYPE (TREE_OPERAND (op->op0, 0))) == ARRAY_TYPE
!       && TREE_CODE (TREE_TYPE (TREE_TYPE (op->op0))) != ARRAY_TYPE)
!     {
!       vn_reference_op_s aref;
!       tree dom;
!       aref.type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (op->op0)));
!       aref.opcode = ARRAY_REF;
!       aref.op0 = integer_zero_node;
!       if ((dom = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (op->op0, 0))))
! 	  && TYPE_MIN_VALUE (dom))
! 	aref.op0 = TYPE_MIN_VALUE (dom);
!       aref.op1 = aref.op0;
!       aref.op2 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (op->op0)));
!       VEC_safe_push (vn_reference_op_s, heap, mem, &aref);
!     }
!   copy_reference_ops_from_ref (TREE_OPERAND (op->op0, 0), &mem);
! 
!   /* Do the replacement - we should have at least one op in mem now.  */
!   if (VEC_length (vn_reference_op_s, mem) == 1)
!     {
!       VEC_replace (vn_reference_op_s, *ops, i - 1,
! 		   VEC_index (vn_reference_op_s, mem, 0));
!       VEC_ordered_remove (vn_reference_op_s, *ops, i);
!       i--;
      }
-   else if (VEC_length (vn_reference_op_s, mem) == 2)
-     {
-       VEC_replace (vn_reference_op_s, *ops, i - 1,
- 		   VEC_index (vn_reference_op_s, mem, 0));
-       VEC_replace (vn_reference_op_s, *ops, i,
- 		   VEC_index (vn_reference_op_s, mem, 1));
-     }
-   else if (VEC_length (vn_reference_op_s, mem) > 2)
-     {
-       VEC_replace (vn_reference_op_s, *ops, i - 1,
- 		   VEC_index (vn_reference_op_s, mem, 0));
-       VEC_replace (vn_reference_op_s, *ops, i,
- 		   VEC_index (vn_reference_op_s, mem, 1));
-       /* ???  There is no VEC_splice.  */
-       for (j = 2; VEC_iterate (vn_reference_op_s, mem, j, op); j++)
- 	VEC_safe_insert (vn_reference_op_s, heap, *ops, ++i, op);
-     }
-   else
-     gcc_unreachable ();
- 
-   VEC_free (vn_reference_op_s, heap, mem);
-   *i_p = i;
  }
  
  /* Optimize the reference REF to a constant if possible or return
--- 953,979 ----
  vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **ops,
  			    unsigned int *i_p)
  {
    unsigned int i = *i_p;
!   vn_reference_op_t op = VEC_index (vn_reference_op_s, *ops, i);
!   vn_reference_op_t mem_op = VEC_index (vn_reference_op_s, *ops, i - 1);
!   tree addr_base;
!   HOST_WIDE_INT addr_offset;
! 
!   /* The only thing we have to do is from &OBJ.foo.bar add the offset
!      from .foo.bar to the preceeding MEM_REF offset and replace the
!      address with &OBJ.  */
!   addr_base = get_addr_base_and_offset (TREE_OPERAND (op->op0, 0),
! 					&addr_offset);
!   gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
!   if (addr_base != op->op0)
!     {
!       double_int off = tree_to_double_int (mem_op->op0);
!       off = double_int_sext (off, TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
!       off = double_int_add (off, shwi_to_double_int (addr_offset
! 						     / BITS_PER_UNIT));
!       mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
!       op->op0 = build_fold_addr_expr (addr_base);
      }
  }
  
  /* Optimize the reference REF to a constant if possible or return
*************** valueize_refs (VEC (vn_reference_op_s, h
*** 1105,1111 ****
  	     a preceding indirect reference.  */
  	  if (i > 0 && TREE_CODE (vro->op0) == ADDR_EXPR
  	      && VEC_index (vn_reference_op_s,
! 			    orig, i - 1)->opcode == INDIRECT_REF)
  	    {
  	      vn_reference_fold_indirect (&orig, &i);
  	      continue;
--- 1070,1076 ----
  	     a preceding indirect reference.  */
  	  if (i > 0 && TREE_CODE (vro->op0) == ADDR_EXPR
  	      && VEC_index (vn_reference_op_s,
! 			    orig, i - 1)->opcode == MEM_REF)
  	    {
  	      vn_reference_fold_indirect (&orig, &i);
  	      continue;



More information about the Gcc-patches mailing list