[PATCH] Fix PR49645, with C FE pieces

Richard Guenther rguenther@suse.de
Wed Jul 6 13:26:00 GMT 2011


This fixes PR49645 - with MEM_REF the value-numbering machinery
to look through aggregate copies wasn't working reliably as
we have two representations for X, X and MEM[&X].  The following
patch fixes that by internally always using the more complicated
representation.

The patch needs consistent DECL_HARD_REGISTER settings to avoid
generating MEM_REFs for them though and the C frontend fails
to set that flag for global variables - hence the c-decl.c part
(otherwise compile.exp 20041119-1.c ICEs).

Bootstrapped and tested on x86_64-unknown-linux-gnu, are the
C frontend parts ok for trunk?

Thanks,
Richard.

2011-07-06  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/49645
	* c-decl.c (finish_decl): Also set DECL_HARD_REGISTER for global
	register variables.
	* tree-ssa-sccvn.c (vn_reference_op_eq): Disregard differences
	in type qualification here ...
	(copy_reference_ops_from_ref): ... not here.
	(vn_reference_lookup_3): ... or here.
	(copy_reference_ops_from_ref): Record decl bases as MEM[&decl].
	(vn_reference_lookup): Do the lookup with a valueized ao-ref.

	* g++.dg/tree-ssa/pr8781.C: Disable SRA.

Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c	(revision 175905)
--- gcc/c-decl.c	(working copy)
*************** finish_decl (tree decl, location_t init_
*** 4357,4362 ****
--- 4357,4364 ----
  	       when a tentative file-scope definition is seen.
  	       But at end of compilation, do output code for them.  */
  	    DECL_DEFER_OUTPUT (decl) = 1;
+ 	  if (asmspec && C_DECL_REGISTER (decl))
+ 	    DECL_HARD_REGISTER (decl) = 1;
  	  rest_of_decl_compilation (decl, true, 0);
  	}
        else
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c	(revision 175905)
--- gcc/tree-ssa-sccvn.c	(working copy)
*************** vn_reference_op_eq (const void *p1, cons
*** 391,401 ****
    const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
    const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
  
!   return vro1->opcode == vro2->opcode
!     && types_compatible_p (vro1->type, vro2->type)
!     && expressions_equal_p (vro1->op0, vro2->op0)
!     && expressions_equal_p (vro1->op1, vro2->op1)
!     && expressions_equal_p (vro1->op2, vro2->op2);
  }
  
  /* Compute the hash for a reference operand VRO1.  */
--- 391,405 ----
    const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
    const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
  
!   return (vro1->opcode == vro2->opcode
! 	  /* We do not care for differences in type qualification.  */
! 	  && (vro1->type == vro2->type
! 	      || (vro1->type && vro2->type
! 		  && types_compatible_p (TYPE_MAIN_VARIANT (vro1->type),
! 					 TYPE_MAIN_VARIANT (vro2->type))))
! 	  && expressions_equal_p (vro1->op0, vro2->op0)
! 	  && expressions_equal_p (vro1->op1, vro2->op1)
! 	  && expressions_equal_p (vro1->op2, vro2->op2));
  }
  
  /* Compute the hash for a reference operand VRO1.  */
*************** copy_reference_ops_from_ref (tree ref, V
*** 579,585 ****
  
        memset (&temp, 0, sizeof (temp));
        /* We do not care for spurious type qualifications.  */
!       temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref));
        temp.opcode = TREE_CODE (ref);
        temp.op0 = TMR_INDEX (ref);
        temp.op1 = TMR_STEP (ref);
--- 583,589 ----
  
        memset (&temp, 0, sizeof (temp));
        /* We do not care for spurious type qualifications.  */
!       temp.type = TREE_TYPE (ref);
        temp.opcode = TREE_CODE (ref);
        temp.op0 = TMR_INDEX (ref);
        temp.op1 = TMR_STEP (ref);
*************** copy_reference_ops_from_ref (tree ref, V
*** 610,617 ****
        vn_reference_op_s temp;
  
        memset (&temp, 0, sizeof (temp));
!       /* We do not care for spurious type qualifications.  */
!       temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref));
        temp.opcode = TREE_CODE (ref);
        temp.off = -1;
  
--- 614,620 ----
        vn_reference_op_s temp;
  
        memset (&temp, 0, sizeof (temp));
!       temp.type = TREE_TYPE (ref);
        temp.opcode = TREE_CODE (ref);
        temp.off = -1;
  
*************** copy_reference_ops_from_ref (tree ref, V
*** 676,691 ****
  		temp.off = off.low;
  	    }
  	  break;
  	case STRING_CST:
  	case INTEGER_CST:
  	case COMPLEX_CST:
  	case VECTOR_CST:
  	case REAL_CST:
  	case CONSTRUCTOR:
- 	case VAR_DECL:
- 	case PARM_DECL:
- 	case CONST_DECL:
- 	case RESULT_DECL:
  	case SSA_NAME:
  	  temp.op0 = ref;
  	  break;
--- 679,711 ----
  		temp.off = off.low;
  	    }
  	  break;
+ 	case VAR_DECL:
+ 	  if (DECL_HARD_REGISTER (ref))
+ 	    {
+ 	      temp.op0 = ref;
+ 	      break;
+ 	    }
+ 	  /* Fallthru.  */
+ 	case PARM_DECL:
+ 	case CONST_DECL:
+ 	case RESULT_DECL:
+ 	  /* Canonicalize decls to MEM[&decl] which is what we end up with
+ 	     when valueizing MEM[ptr] with ptr = &decl.  */
+ 	  temp.opcode = MEM_REF;
+ 	  temp.op0 = build_int_cst (build_pointer_type (TREE_TYPE (ref)), 0);
+ 	  temp.off = 0;
+ 	  VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+ 	  temp.opcode = ADDR_EXPR;
+ 	  temp.op0 = build_fold_addr_expr (ref);
+ 	  temp.type = TREE_TYPE (temp.op0);
+ 	  temp.off = -1;
+ 	  break;
  	case STRING_CST:
  	case INTEGER_CST:
  	case COMPLEX_CST:
  	case VECTOR_CST:
  	case REAL_CST:
  	case CONSTRUCTOR:
  	case SSA_NAME:
  	  temp.op0 = ref;
  	  break;
*************** vn_reference_lookup_3 (ao_ref *ref, tree
*** 1580,1586 ****
        op.op0 = build_int_cst (ptr_type_node, at - rhs_offset);
        op.off = at - lhs_offset + rhs_offset;
        VEC_replace (vn_reference_op_s, vr->operands, 0, &op);
!       op.type = TYPE_MAIN_VARIANT (TREE_TYPE (rhs));
        op.opcode = TREE_CODE (rhs);
        op.op0 = rhs;
        op.off = -1;
--- 1600,1606 ----
        op.op0 = build_int_cst (ptr_type_node, at - rhs_offset);
        op.off = at - lhs_offset + rhs_offset;
        VEC_replace (vn_reference_op_s, vr->operands, 0, &op);
!       op.type = TREE_TYPE (rhs);
        op.opcode = TREE_CODE (rhs);
        op.op0 = rhs;
        op.off = -1;
*************** vn_reference_lookup (tree op, tree vuse,
*** 1692,1698 ****
      {
        vn_reference_t wvnresult;
        ao_ref r;
!       ao_ref_init (&r, op);
        vn_walk_kind = kind;
        wvnresult =
  	(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
--- 1712,1723 ----
      {
        vn_reference_t wvnresult;
        ao_ref r;
!       /* Make sure to use a valueized reference ...  */
!       if (!ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type, vr1.operands))
! 	ao_ref_init (&r, op);
!       else
! 	/* ... but also preserve a full reference tree for advanced TBAA.  */
! 	r.ref = op;
        vn_walk_kind = kind;
        wvnresult =
  	(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
Index: gcc/testsuite/g++.dg/tree-ssa/pr8781.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/pr8781.C	(revision 175905)
--- gcc/testsuite/g++.dg/tree-ssa/pr8781.C	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O -fdump-tree-fre1-details" } */
  
  int f();
  
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O -fno-tree-sra -fdump-tree-fre1-details" } */
  
  int f();
  



More information about the Gcc-patches mailing list