Hi!

On the attached testcase we ICE, because cselim uses
   if (!is_gimple_reg_type (TREE_TYPE (lhs))
       || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0))
to guard an optimization, and we have two MEM_REFs where operand_equal_p
is true, but they don't have compatible types (the first one is _Complex
double, i.e. is_gimple_reg_type), the second has aggregate type of the
same size/same mode (structure containing the _Complex double).

The first patch is what I've bootstrapped/regtested on i686-linux so far
(x86_64-linux regtest still pending), it seems to trigger different return
value from operand_equal_p in a couple of TUs:
c52008b.adb
/usr/src/gcc-4.8/libstdc++-v3/src/c++98/complex_io.cc
/usr/src/gcc-4.8/lto-plugin/lto-plugin.c
/usr/src/gcc-4.8/gcc/testsuite/g++.dg/opt/pr47366.C
/usr/src/gcc-4.8/gcc/testsuite/g++.dg/torture/pr56635.C
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/actual_array_constructor_1.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/alloc_comp_assign_2.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/alloc_comp_assign_3.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/argument_checking_1.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/array_memcpy_2.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/array_temporaries_3.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/auto_char_len_3.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/char_pointer_func.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/proc_ptr_23.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/pure_byref_1.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/realloc_on_assign_17.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/reshape.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/string_ctor_1.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/unlimited_polymorphic_1.f03
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/vector_subscript_2.f90
/usr/src/gcc-4.8/gcc/testsuite/gfortran.dg/widechar_8.f90
/usr/src/gcc-4.8/libstdc++-v3/testsuite/23_containers/unordered_map/cons/56112.cc
/usr/src/gcc-4.8/libstdc++-v3/testsuite/25_algorithms/remove_if/moveable.cc
/usr/src/gcc-4.8/libstdc++-v3/testsuite/25_algorithms/remove/moveable.cc
/usr/src/gcc-4.8/libstdc++-v3/testsuite/25_algorithms/stable_sort/49559.cc
but from quick look at some of them it didn't look like something very
undesirable.  In any case, no new FAILs.  Ok for trunk if it passes regtest
on x86_64-linux too?

The second patch is a safer version intended for 4.8.0, to be
bootstrapped/regtested afterwards.

        Jakub
2013-03-18  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/56635
        * fold-const.c (operand_equal_p): For MEM_REF and TARGET_MEM_REF,
        require types_compatible_p types.

        * g++.dg/torture/pr56635.C: New test.

--- gcc/fold-const.c.jj 2013-02-26 10:59:53.000000000 +0100
+++ gcc/fold-const.c    2013-03-18 10:20:41.368932746 +0100
@@ -2572,13 +2572,14 @@ operand_equal_p (const_tree arg0, const_
          flags &= ~OEP_CONSTANT_ADDRESS_OF;
          /* Require equal access sizes, and similar pointer types.
             We can have incomplete types for array references of
-            variable-sized arrays from the Fortran frontent
-            though.  */
+            variable-sized arrays from the Fortran frontend
+            though.  Also verify the types are compatible.  */
          return ((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1))
                   || (TYPE_SIZE (TREE_TYPE (arg0))
                       && TYPE_SIZE (TREE_TYPE (arg1))
                       && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
                                           TYPE_SIZE (TREE_TYPE (arg1)), 
flags)))
+                 && types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))
                  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1)))
                      == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
                  && OP_SAME (0) && OP_SAME (1));
--- gcc/testsuite/g++.dg/torture/pr56635.C.jj   2013-03-18 09:56:28.089526657 
+0100
+++ gcc/testsuite/g++.dg/torture/pr56635.C      2013-03-18 09:56:36.111478322 
+0100
@@ -0,0 +1,17 @@
+// PR tree-optimization/56635
+// { dg-do compile }
+
+struct A { _Complex double a; };
+
+void
+foo (A **x, A **y)
+{
+  A r;
+  if (__real__ x[0]->a)
+    {
+      r.a = y[0]->a / x[0]->a;
+      **x = r;
+    }
+  else
+    **x = **y;
+}
2013-03-18  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/56635
        * tree-ssa-phiopt.c (cond_if_else_store_replacement_1): Give up
        if lhs of then_assign and else_assign don't have compatible types.

        * g++.dg/torture/pr56635.C: New test.

--- gcc/tree-ssa-phiopt.c.jj    2013-02-13 21:47:17.000000000 +0100
+++ gcc/tree-ssa-phiopt.c       2013-03-18 09:54:03.047377144 +0100
@@ -1528,7 +1528,7 @@ cond_if_else_store_replacement_1 (basic_
                                  basic_block join_bb, gimple then_assign,
                                  gimple else_assign)
 {
-  tree lhs_base, lhs, then_rhs, else_rhs, name;
+  tree lhs_base, lhs, else_lhs, then_rhs, else_rhs, name;
   source_location then_locus, else_locus;
   gimple_stmt_iterator gsi;
   gimple newphi, new_stmt;
@@ -1544,8 +1544,10 @@ cond_if_else_store_replacement_1 (basic_
     return false;
 
   lhs = gimple_assign_lhs (then_assign);
+  else_lhs = gimple_assign_lhs (else_assign);
   if (!is_gimple_reg_type (TREE_TYPE (lhs))
-      || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0))
+      || !operand_equal_p (lhs, else_lhs, 0)
+      || !types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (else_lhs)))
     return false;
 
   lhs_base = get_base_address (lhs);
--- gcc/testsuite/g++.dg/torture/pr56635.C.jj   2013-03-18 09:56:28.089526657 
+0100
+++ gcc/testsuite/g++.dg/torture/pr56635.C      2013-03-18 09:56:36.111478322 
+0100
@@ -0,0 +1,17 @@
+// PR tree-optimization/56635
+// { dg-do compile }
+
+struct A { _Complex double a; };
+
+void
+foo (A **x, A **y)
+{
+  A r;
+  if (__real__ x[0]->a)
+    {
+      r.a = y[0]->a / x[0]->a;
+      **x = r;
+    }
+  else
+    **x = **y;
+}

Reply via email to