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  <rguent...@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();
  

Reply via email to