public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][mem-ref2] Handle different canonicalizations of memory in SCCVN
@ 2010-06-16 12:26 Richard Guenther
  0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2010-06-16 12:26 UTC (permalink / raw)
  To: gcc-patches


This patch brings a significant reduction in optimization testcase
fails.  The VN code needs some TLC still, but the current state
serves as a nice baseline for followup patches.

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

+FAIL: gfortran.dg/dynamic_dispatch_6.f03  -O2  execution test

now fails - I suppose Fortran does sth funny.

Richard.

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

	* tree-ssa-sccvn.h (struct vn_reference_op_struct): Add
	a field to store the constant offset this op applies.
	* tree-ssa-sscvn.c (vn_reference_compute_hash): Hash
	fields that only adjust the offset by a constant by
	aggregating them and hashing the offset.  Do not hash
	*& combinations.
	(vn_reference_eq): Adjust comparison accordingly.  Make sure
	accesses are of the same size first.
	(copy_reference_ops_from_ref): Compute and remember constant
	offsets.
	(copy_reference_ops_from_call): Likewise.
	* tree-ssa-pre.c (insert_into_preds_of_block): Properly
	initialize avail.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c	(revision 160753)
--- gcc/tree-ssa-sccvn.c	(working copy)
*************** vn_reference_compute_hash (const vn_refe
*** 431,439 ****
    hashval_t result = 0;
    int i;
    vn_reference_op_t vro;
  
    for (i = 0; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro); i++)
!     result = vn_reference_op_compute_hash (vro, result);
    if (vr1->vuse)
      result += SSA_NAME_VERSION (vr1->vuse);
  
--- 431,471 ----
    hashval_t result = 0;
    int i;
    vn_reference_op_t vro;
+   HOST_WIDE_INT off = -1;
+   bool deref = false;
  
    for (i = 0; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro); i++)
!     {
!       if (vro->opcode == MEM_REF)
! 	deref = true;
!       else if (vro->opcode != ADDR_EXPR)
! 	deref = false;
!       if (vro->off != -1)
! 	{
! 	  if (off == -1)
! 	    off = 0;
! 	  off += vro->off;
! 	}
!       else
! 	{
! 	  if (off != -1
! 	      && off != 0)
! 	    result = iterative_hash_hashval_t (off, result);
! 	  off = -1;
! 	  if (deref
! 	      && vro->opcode == ADDR_EXPR)
! 	    {
! 	      if (vro->op0)
! 		{
! 		  tree op = TREE_OPERAND (vro->op0, 0);
! 		  result = iterative_hash_hashval_t (TREE_CODE (op), result);
! 		  result = iterative_hash_expr (op, result);
! 		}
! 	    }
! 	  else
! 	    result = vn_reference_op_compute_hash (vro, result);
! 	}
!     }
    if (vr1->vuse)
      result += SSA_NAME_VERSION (vr1->vuse);
  
*************** vn_reference_compute_hash (const vn_refe
*** 446,453 ****
  int
  vn_reference_eq (const void *p1, const void *p2)
  {
!   int i;
!   vn_reference_op_t vro;
  
    const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
    const_vn_reference_t const vr2 = (const_vn_reference_t) p2;
--- 478,484 ----
  int
  vn_reference_eq (const void *p1, const void *p2)
  {
!   unsigned i, j;
  
    const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
    const_vn_reference_t const vr2 = (const_vn_reference_t) p2;
*************** vn_reference_eq (const void *p1, const v
*** 466,482 ****
    if (vr1->operands == vr2->operands)
      return true;
  
!   /* We require that address operands be canonicalized in a way that
!      two memory references will have the same operands if they are
!      equivalent.  */
!   if (VEC_length (vn_reference_op_s, vr1->operands)
!       != VEC_length (vn_reference_op_s, vr2->operands))
      return false;
  
!   for (i = 0; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro); i++)
!     if (!vn_reference_op_eq (VEC_index (vn_reference_op_s, vr2->operands, i),
! 			     vro))
!       return false;
  
    return true;
  }
--- 497,554 ----
    if (vr1->operands == vr2->operands)
      return true;
  
!   if (!expressions_equal_p (TYPE_SIZE (vr1->type), TYPE_SIZE (vr2->type)))
      return false;
  
!   i = 0;
!   j = 0;
!   do
!     {
!       HOST_WIDE_INT off1 = 0, off2 = 0;
!       vn_reference_op_t vro1, vro2;
!       vn_reference_op_s tem1, tem2;
!       bool deref1 = false, deref2 = false;
!       for (; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro1); i++)
! 	{
! 	  if (vro1->opcode == MEM_REF)
! 	    deref1 = true;
! 	  if (vro1->off == -1)
! 	    break;
! 	  off1 += vro1->off;
! 	}
!       for (; VEC_iterate (vn_reference_op_s, vr2->operands, j, vro2); j++)
! 	{
! 	  if (vro2->opcode == MEM_REF)
! 	    deref2 = true;
! 	  if (vro2->off == -1)
! 	    break;
! 	  off2 += vro2->off;
! 	}
!       if (off1 != off2)
! 	return false;
!       if (deref1 && vro1->opcode == ADDR_EXPR)
! 	{
! 	  memset (&tem1, 0, sizeof (tem1));
! 	  tem1.op0 = TREE_OPERAND (vro1->op0, 0);
! 	  tem1.type = TREE_TYPE (tem1.op0);
! 	  tem1.opcode = TREE_CODE (tem1.op0);
! 	  vro1 = &tem1;
! 	}
!       if (deref2 && vro2->opcode == ADDR_EXPR)
! 	{
! 	  memset (&tem2, 0, sizeof (tem2));
! 	  tem2.op0 = TREE_OPERAND (vro2->op0, 0);
! 	  tem2.type = TREE_TYPE (tem2.op0);
! 	  tem2.opcode = TREE_CODE (tem2.op0);
! 	  vro2 = &tem2;
! 	}
!       if (!vn_reference_op_eq (vro1, vro2))
! 	return false;
!       ++j;
!       ++i;
!     }
!   while (VEC_length (vn_reference_op_s, vr1->operands) != i
! 	 || VEC_length (vn_reference_op_s, vr2->operands) != j);
  
    return true;
  }
*************** copy_reference_ops_from_ref (tree ref, V
*** 503,508 ****
--- 575,581 ----
        temp.op0 = TMR_INDEX (ref);
        temp.op1 = TMR_STEP (ref);
        temp.op2 = TMR_OFFSET (ref);
+       temp.off = -1;
        VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
  
        memset (&temp, 0, sizeof (temp));
*************** copy_reference_ops_from_ref (tree ref, V
*** 510,515 ****
--- 583,589 ----
        temp.opcode = TREE_CODE (base);
        temp.op0 = base;
        temp.op1 = TMR_ORIGINAL (ref);
+       temp.off = -1;
        VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
        return;
      }
*************** copy_reference_ops_from_ref (tree ref, V
*** 524,542 ****
        /* We do not care for spurious type qualifications.  */
        temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref));
        temp.opcode = TREE_CODE (ref);
  
        switch (temp.opcode)
  	{
  	case ALIGN_INDIRECT_REF:
  	  /* The only operand is the address, which gets its own
  	     vn_reference_op_s structure.  */
! 	    break;
  	case MISALIGNED_INDIRECT_REF:
  	  temp.op0 = TREE_OPERAND (ref, 1);
  	  break;
  	case MEM_REF:
  	  /* The base address gets its own vn_reference_op_s structure.  */
  	  temp.op0 = TREE_OPERAND (ref, 1);
  	  break;
  	case BIT_FIELD_REF:
  	  /* Record bits and position.  */
--- 598,620 ----
        /* We do not care for spurious type qualifications.  */
        temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref));
        temp.opcode = TREE_CODE (ref);
+       temp.off = -1;
  
        switch (temp.opcode)
  	{
  	case ALIGN_INDIRECT_REF:
  	  /* The only operand is the address, which gets its own
  	     vn_reference_op_s structure.  */
! 	  break;
  	case MISALIGNED_INDIRECT_REF:
  	  temp.op0 = TREE_OPERAND (ref, 1);
+ 	  temp.off = 0;
  	  break;
  	case MEM_REF:
  	  /* The base address gets its own vn_reference_op_s structure.  */
  	  temp.op0 = TREE_OPERAND (ref, 1);
+ 	  if (host_integerp (TREE_OPERAND (ref, 1), 0))
+ 	    temp.off = TREE_INT_CST_LOW (TREE_OPERAND (ref, 1));
  	  break;
  	case BIT_FIELD_REF:
  	  /* Record bits and position.  */
*************** copy_reference_ops_from_ref (tree ref, V
*** 561,566 ****
--- 639,663 ----
  	      && integer_zerop (DECL_FIELD_BIT_OFFSET (temp.op0))
  	      && host_integerp (DECL_SIZE (temp.op0), 0))
  	    temp.op0 = DECL_SIZE (temp.op0);
+ 	  {
+ 	    tree this_offset = component_ref_field_offset (ref);
+ 	    if (this_offset
+ 		&& TREE_CODE (this_offset) == INTEGER_CST)
+ 	      {
+ 		tree bit_offset = DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1));
+ 		if (TREE_INT_CST_LOW (bit_offset) % BITS_PER_UNIT == 0)
+ 		  {
+ 		    double_int off
+ 		      = double_int_add (tree_to_double_int (this_offset),
+ 					double_int_sdiv
+ 					  (tree_to_double_int (bit_offset),
+ 					   uhwi_to_double_int (BITS_PER_UNIT),
+ 					   TRUNC_DIV_EXPR));
+ 		    if (double_int_fits_in_shwi_p (off))
+ 		      temp.off = off.low;
+ 		  }
+ 	      }
+ 	  }
  	  break;
  	case ARRAY_RANGE_REF:
  	case ARRAY_REF:
*************** copy_reference_ops_from_ref (tree ref, V
*** 569,574 ****
--- 666,683 ----
  	  /* Always record lower bounds and element size.  */
  	  temp.op1 = array_ref_low_bound (ref);
  	  temp.op2 = array_ref_element_size (ref);
+ 	  if (TREE_CODE (temp.op0) == INTEGER_CST
+ 	      && TREE_CODE (temp.op1) == INTEGER_CST
+ 	      && TREE_CODE (temp.op2) == INTEGER_CST)
+ 	    {
+ 	      double_int off = tree_to_double_int (temp.op0);
+ 	      off = double_int_add (off,
+ 				    double_int_neg
+ 				      (tree_to_double_int (temp.op1)));
+ 	      off = double_int_mul (off, tree_to_double_int (temp.op2));
+ 	      if (double_int_fits_in_shwi_p (off))
+ 		temp.off = off.low;
+ 	    }
  	  break;
  	case STRING_CST:
  	case INTEGER_CST:
*************** copy_reference_ops_from_ref (tree ref, V
*** 595,603 ****
  	     ref in the chain of references (IE they require an
  	     operand), so we don't have to put anything
  	     for op* as it will be handled by the iteration  */
- 	case IMAGPART_EXPR:
  	case REALPART_EXPR:
  	case VIEW_CONVERT_EXPR:
  	  break;
  	default:
  	  gcc_unreachable ();
--- 704,716 ----
  	     ref in the chain of references (IE they require an
  	     operand), so we don't have to put anything
  	     for op* as it will be handled by the iteration  */
  	case REALPART_EXPR:
  	case VIEW_CONVERT_EXPR:
+ 	  temp.off = 0;
+ 	  break;
+ 	case IMAGPART_EXPR:
+ 	  /* This is only interesting for its constant offset.  */
+ 	  temp.off = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (ref)));
  	  break;
  	default:
  	  gcc_unreachable ();
*************** copy_reference_ops_from_call (gimple cal
*** 798,803 ****
--- 911,917 ----
    temp.opcode = CALL_EXPR;
    temp.op0 = gimple_call_fn (call);
    temp.op1 = gimple_call_chain (call);
+   temp.off = -1;
    VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
  
    /* Copy the call arguments.  As they can be references as well,
Index: gcc/tree-ssa-sccvn.h
===================================================================
*** gcc/tree-ssa-sccvn.h	(revision 160753)
--- gcc/tree-ssa-sccvn.h	(working copy)
*************** typedef const struct vn_phi_s *const_vn_
*** 72,77 ****
--- 72,79 ----
  typedef struct vn_reference_op_struct
  {
    enum tree_code opcode;
+   /* Constant offset this op adds or -1 if it is variable.  */
+   HOST_WIDE_INT off;
    tree type;
    tree op0;
    tree op1;
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 160753)
--- gcc/tree-ssa-pre.c	(working copy)
*************** insert_into_preds_of_block (basic_block
*** 3332,3337 ****
--- 3332,3339 ----
  		      avail[bprime->index] = get_or_alloc_expr_for_name (forcedexpr);
  		    }
  		}
+ 	      else
+ 		avail[bprime->index] = get_or_alloc_expr_for_constant (builtexpr);
  	    }
  	}
        else if (eprime->kind == NAME)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-06-16  9:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-16 12:26 [PATCH][mem-ref2] Handle different canonicalizations of memory in SCCVN Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).