Independent on the outcome of the discussion regarding to comparing
ADDR_EXPRs in operand_equal_p the following presents a more
backportable fix for the SCCVN endless loop.  We know that we
compare is_gimple_min_invariant addresses which means we can
resort to a get_addr_base_and_unit_offset comparison to double-check
the operand_equal_p result.

For now I'll revert the previous change to the operand_equal_p behavior.

Bootstrap / regtest pending on x86_64-unknown-linux-gnu.

Richard.

2013-05-27  Richard Biener  <rguent...@suse.de>

        Revert
        PR middle-end/57381
        * fold-const.c (operand_equal_p): Compare FIELD_DECLs with
        OEP_CONSTANT_ADDRESS_OF retained.

        PR tree-optimization/57417
        * tree-ssa-sccvn.c (vn_reference_fold_indirect): Fix test
        for unchanged base.
        (set_ssa_val_to): Compare addresses using
        get_addr_base_and_unit_offset.

        * gcc.dg/torture/pr57417.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 199350)
--- gcc/fold-const.c    (working copy)
*************** operand_equal_p (const_tree arg0, const_
*** 2664,2673 ****
        case COMPONENT_REF:
          /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
             may be NULL when we're called to compare MEM_EXPRs.  */
!         if (!OP_SAME_WITH_NULL (0) || !OP_SAME (1))
            return 0;
          flags &= ~OEP_CONSTANT_ADDRESS_OF;
!         return OP_SAME_WITH_NULL (2);
  
        case BIT_FIELD_REF:
          if (!OP_SAME (0))
--- 2664,2673 ----
        case COMPONENT_REF:
          /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
             may be NULL when we're called to compare MEM_EXPRs.  */
!         if (!OP_SAME_WITH_NULL (0))
            return 0;
          flags &= ~OEP_CONSTANT_ADDRESS_OF;
!         return OP_SAME (1) && OP_SAME_WITH_NULL (2);
  
        case BIT_FIELD_REF:
          if (!OP_SAME (0))
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c        (revision 199350)
--- gcc/tree-ssa-sccvn.c        (working copy)
*************** vn_reference_fold_indirect (vec<vn_refer
*** 1145,1151 ****
    addr_base = get_addr_base_and_unit_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 = off.sext (TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
--- 1145,1151 ----
    addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (op->op0, 0),
                                             &addr_offset);
    gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
!   if (addr_base != TREE_OPERAND (op->op0, 0))
      {
        double_int off = tree_to_double_int (mem_op->op0);
        off = off.sext (TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
*************** static inline bool
*** 2608,2613 ****
--- 2608,2614 ----
  set_ssa_val_to (tree from, tree to)
  {
    tree currval = SSA_VAL (from);
+   HOST_WIDE_INT toff, coff;
  
    if (from != to)
      {
*************** set_ssa_val_to (tree from, tree to)
*** 2643,2649 ****
        print_generic_expr (dump_file, to, 0);
      }
  
!   if (currval != to  && !operand_equal_p (currval, to, OEP_PURE_SAME))
      {
        VN_INFO (from)->valnum = to;
        if (dump_file && (dump_flags & TDF_DETAILS))
--- 2644,2660 ----
        print_generic_expr (dump_file, to, 0);
      }
  
!   if (currval != to
!       && !operand_equal_p (currval, to, 0)
!       /* ???  For addresses involving volatile objects or types 
operand_equal_p
!          does not reliably detect ADDR_EXPRs as equal.  We know we are only
!        getting invariant gimple addresses here, so can use
!        get_addr_base_and_unit_offset to do this comparison.  */
!       && !(TREE_CODE (currval) == ADDR_EXPR
!          && TREE_CODE (to) == ADDR_EXPR
!          && (get_addr_base_and_unit_offset (TREE_OPERAND (currval, 0), &coff)
!              == get_addr_base_and_unit_offset (TREE_OPERAND (to, 0), &toff))
!          && coff == toff))
      {
        VN_INFO (from)->valnum = to;
        if (dump_file && (dump_flags & TDF_DETAILS))
Index: gcc/testsuite/gcc.dg/torture/pr57417.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57417.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57417.c      (working copy)
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ 
+ int a, b;
+ volatile int *c;
+ 
+ void foo ()
+ {
+   volatile int d[1];
+   b = 0;
+   for (;; a--)
+     c = &d[b];
+ }

Reply via email to