re PR tree-optimization/71901 (ice in find_or_generate_expression)
authorRichard Biener <rguenther@suse.de>
Tue, 19 Jul 2016 10:19:46 +0000 (10:19 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 19 Jul 2016 10:19:46 +0000 (10:19 +0000)
2016-07-19  Richard Biener  <rguenther@suse.de>

PR tree-optimization/71901
* tree-ssa-sccvn.h (struct vn_reference_op_struct): Add
align member, group stuff with the bitfield.
(vn_ref_op_align_unit): New inline.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): For ARRAY_REFs
record element alignment and operand 3 unchanged.
(ao_ref_init_from_vn_reference): Adjust.
(valueize_refs_1): Likewise.
* tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise.

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

From-SVN: r238468

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr71901.c [new file with mode: 0644]
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h

index 1c57adc9543dcbd5c151ba2c5342bcb5060b1ab1..271706c02001e5bae72f713ab461de4ddeb19673 100644 (file)
@@ -1,4 +1,16 @@
-2016-07-18  Richard Biener  <rguenther@suse.de>
+2016-07-19  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/71901
+       * tree-ssa-sccvn.h (struct vn_reference_op_struct): Add
+       align member, group stuff with the bitfield.
+       (vn_ref_op_align_unit): New inline.
+       * tree-ssa-sccvn.c (copy_reference_ops_from_ref): For ARRAY_REFs
+       record element alignment and operand 3 unchanged.
+       (ao_ref_init_from_vn_reference): Adjust.
+       (valueize_refs_1): Likewise.
+       * tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise.
+
+2016-07-19  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/71908
        * tree-ssa-structalias.c (get_constraint_for_component_ref): Handle
index d0a3fcb37640bd98b5e62e2d0c03c3ee5d73bb6b..457eb1094db007960567998071de74cb3a627a45 100644 (file)
@@ -1,4 +1,9 @@
-2016-07-18  Richard Biener  <rguenther@suse.de>
+2016-07-19  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/71901
+       * gcc.dg/torture/pr71901.c: New testcase.
+
+2016-07-19  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/71908
        * gcc.dg/torture/pr71908.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/torture/pr71901.c b/gcc/testsuite/gcc.dg/torture/pr71901.c
new file mode 100644 (file)
index 0000000..0be1d73
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+typedef struct { int _mp_size; } mpz_t[1];
+int a, b;
+void fn1()
+{
+  mpz_t c[1][b];
+  for (;;) {
+      int d = 0 >= 0 ? 0 == 0 ? c[0][0]->_mp_size ? -1 : 0 : 0 : 0,
+         e = 0 >= 0 ? 0 == 0 ? c[1][1]->_mp_size ? -1 : 0 : 0 : 0;
+      if (d != e)
+       a++;
+  }
+}
index c59aab8d0ff32ebff43702143691b249619c11ce..a5f34862417dde9dc0d18846d85254e4855fdb6e 100644 (file)
@@ -2570,15 +2570,14 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
               here as the element alignment may be not visible.  See
               PR43783.  Simply drop the element size for constant
               sizes.  */
-           if (tree_int_cst_equal (genop3, TYPE_SIZE_UNIT (elmt_type)))
+           if (TREE_CODE (genop3) == INTEGER_CST
+               && TREE_CODE (TYPE_SIZE_UNIT (elmt_type)) == INTEGER_CST
+               && wi::eq_p (wi::to_offset (TYPE_SIZE_UNIT (elmt_type)),
+                            (wi::to_offset (genop3)
+                             * vn_ref_op_align_unit (currop))))
              genop3 = NULL_TREE;
            else
              {
-               genop3 = size_binop (EXACT_DIV_EXPR, genop3,
-                                    size_int (TYPE_ALIGN_UNIT (elmt_type)));
-               /* We may have a useless conversion added by
-                  array_ref_element_size via copy_reference_opts_from_ref.  */
-               STRIP_USELESS_TYPE_CONVERSION (genop3);
                genop3 = find_or_generate_expression (block, genop3, stmts);
                if (!genop3)
                  return NULL_TREE;
index b1f10d50771d66c6d715c3fe462dc034afb187de..e6853420b6c90cd57fc7616837ed1c646d24da12 100644 (file)
@@ -805,24 +805,30 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
          break;
        case ARRAY_RANGE_REF:
        case ARRAY_REF:
-         /* Record index as operand.  */
-         temp.op0 = TREE_OPERAND (ref, 1);
-         /* Always record lower bounds and element size.  */
-         temp.op1 = array_ref_low_bound (ref);
-         temp.op2 = array_ref_element_size (ref);
-         /* array_ref_element_size forces the result to sizetype
-            even if that is the same as bitsizetype.  */
-         STRIP_USELESS_TYPE_CONVERSION (temp.op2);
-         if (TREE_CODE (temp.op0) == INTEGER_CST
-             && TREE_CODE (temp.op1) == INTEGER_CST
-             && TREE_CODE (temp.op2) == INTEGER_CST)
-           {
-             offset_int off = ((wi::to_offset (temp.op0)
-                                - wi::to_offset (temp.op1))
-                               * wi::to_offset (temp.op2));
-             if (wi::fits_shwi_p (off))
-               temp.off = off.to_shwi();
-           }
+         {
+           tree eltype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0)));
+           /* Record index as operand.  */
+           temp.op0 = TREE_OPERAND (ref, 1);
+           /* Always record lower bounds and element size.  */
+           temp.op1 = array_ref_low_bound (ref);
+           /* But record element size in units of the type alignment.  */
+           temp.op2 = TREE_OPERAND (ref, 3);
+           temp.align = eltype->type_common.align;
+           if (! temp.op2)
+             temp.op2 = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (eltype),
+                                    size_int (TYPE_ALIGN_UNIT (eltype)));
+           if (TREE_CODE (temp.op0) == INTEGER_CST
+               && TREE_CODE (temp.op1) == INTEGER_CST
+               && TREE_CODE (temp.op2) == INTEGER_CST)
+             {
+               offset_int off = ((wi::to_offset (temp.op0)
+                                  - wi::to_offset (temp.op1))
+                                 * wi::to_offset (temp.op2)
+                                 * vn_ref_op_align_unit (&temp));
+               if (wi::fits_shwi_p (off))
+                 temp.off = off.to_shwi();
+             }
+         }
          break;
        case VAR_DECL:
          if (DECL_HARD_REGISTER (ref))
@@ -1021,7 +1027,7 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
              offset_int woffset
                = wi::sext (wi::to_offset (op->op0) - wi::to_offset (op->op1),
                            TYPE_PRECISION (TREE_TYPE (op->op0)));
-             woffset *= wi::to_offset (op->op2);
+             woffset *= wi::to_offset (op->op2) * vn_ref_op_align_unit (op);
              woffset <<= LOG2_BITS_PER_UNIT;
              offset += woffset;
            }
@@ -1471,7 +1477,8 @@ valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything)
        {
          offset_int off = ((wi::to_offset (vro->op0)
                             - wi::to_offset (vro->op1))
-                           * wi::to_offset (vro->op2));
+                           * wi::to_offset (vro->op2)
+                           * vn_ref_op_align_unit (vro));
          if (wi::fits_shwi_p (off))
            vro->off = off.to_shwi ();
        }
index 92c255d93d2b072b803f6c37fff30b3363124767..d77dbaf42c0d42d7f4fa9626dd2f607dcb9e2b69 100644 (file)
@@ -81,22 +81,29 @@ typedef const struct vn_phi_s *const_vn_phi_t;
 typedef struct vn_reference_op_struct
 {
   ENUM_BITFIELD(tree_code) opcode : 16;
-  /* 1 for instrumented calls.  */
-  unsigned with_bounds : 1;
   /* Dependence info, used for [TARGET_]MEM_REF only.  */
   unsigned short clique;
   unsigned short base;
+  /* 1 for instrumented calls.  */
+  unsigned with_bounds : 1;
+  unsigned reverse : 1;
+  /* For storing TYPE_ALIGN for array ref element size computation.  */
+  unsigned align : 6;
   /* Constant offset this op adds or -1 if it is variable.  */
   HOST_WIDE_INT off;
   tree type;
   tree op0;
   tree op1;
   tree op2;
-  bool reverse;
 } vn_reference_op_s;
 typedef vn_reference_op_s *vn_reference_op_t;
 typedef const vn_reference_op_s *const_vn_reference_op_t;
 
+inline unsigned
+vn_ref_op_align_unit (vn_reference_op_t op)
+{
+  return op->align ? ((unsigned)1 << (op->align - 1)) / BITS_PER_UNIT : 0;
+}
 
 /* A reference operation in the hashtable is representation as
    the vuse, representing the memory state at the time of