re PR ipa/65270 (issues with merging memory accesses from different code paths)
authorRichard Biener <rguenther@suse.de>
Mon, 9 Mar 2015 13:54:28 +0000 (13:54 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 9 Mar 2015 13:54:28 +0000 (13:54 +0000)
2015-03-09  Richard Biener  <rguenther@suse.de>

PR middle-end/65270
* tree-core.h (enum operand_equal_flag): Add OEP_ADDRESS_OF.
* fold-const.c (operand_equal_p): When recursing for ADDR_EXPRs
operand set OEP_ADDRESS_OF.  Clear it when recursing to non-bases
of that.  When comparing dereferences compare alignment.
When comparing MEM_REFs or TARGET_MEM_REFs compare dependence info.

* gcc.dg/torture/pr65270-1.c: New testcase.
* gcc.dg/torture/pr65270-2.c: Likewise.

From-SVN: r221281

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr65270-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr65270-2.c [new file with mode: 0644]
gcc/tree-core.h

index 62b299f0d00fe6e9eaf1eb76c8e6ac27fc969bb7..19efa1eca4e223307297c1236ab63cac0f6b45a1 100644 (file)
@@ -1,3 +1,12 @@
+2015-03-09  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/65270
+       * tree-core.h (enum operand_equal_flag): Add OEP_ADDRESS_OF.
+       * fold-const.c (operand_equal_p): When recursing for ADDR_EXPRs
+       operand set OEP_ADDRESS_OF.  Clear it when recursing to non-bases
+       of that.  When comparing dereferences compare alignment.
+       When comparing MEM_REFs or TARGET_MEM_REFs compare dependence info.
+
 2015-03-08  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-inline-analysis.c (check_callers): Check
index 0834d47fa03b4fdc52e569e20cdf2495ebf1e3cc..915d6395382312f520f3c8fd5728c402e33cf725 100644 (file)
@@ -2860,7 +2860,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       case ADDR_EXPR:
        return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
                                TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1)
-                               ? OEP_CONSTANT_ADDRESS_OF : 0);
+                               ? OEP_CONSTANT_ADDRESS_OF | OEP_ADDRESS_OF : 0);
       default:
        break;
       }
@@ -2922,7 +2922,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
-         flags &= ~OEP_CONSTANT_ADDRESS_OF;
+         if (!(flags & OEP_ADDRESS_OF)
+             && (TYPE_ALIGN (TREE_TYPE (arg0))
+                 != TYPE_ALIGN (TREE_TYPE (arg1))))
+           return 0;
+         flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
          return OP_SAME (0);
 
        case REALPART_EXPR:
@@ -2930,7 +2934,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
          return OP_SAME (0);
 
        case TARGET_MEM_REF:
-         flags &= ~OEP_CONSTANT_ADDRESS_OF;
+         flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
          /* Require equal extra operands and then fall through to MEM_REF
             handling of the two common operands.  */
          if (!OP_SAME_WITH_NULL (2)
@@ -2939,7 +2943,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
            return 0;
          /* Fallthru.  */
        case MEM_REF:
-         flags &= ~OEP_CONSTANT_ADDRESS_OF;
+         flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_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 frontend
@@ -2950,9 +2954,16 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                       && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
                                           TYPE_SIZE (TREE_TYPE (arg1)), flags)))
                  && types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))
-                 && alias_ptr_types_compatible_p
-                      (TREE_TYPE (TREE_OPERAND (arg0, 1)),
-                       TREE_TYPE (TREE_OPERAND (arg1, 1)))
+                 && ((flags & OEP_ADDRESS_OF)
+                     || (alias_ptr_types_compatible_p
+                           (TREE_TYPE (TREE_OPERAND (arg0, 1)),
+                            TREE_TYPE (TREE_OPERAND (arg1, 1)))
+                         && (MR_DEPENDENCE_CLIQUE (arg0)
+                             == MR_DEPENDENCE_CLIQUE (arg1))
+                         && (MR_DEPENDENCE_BASE (arg0)
+                             == MR_DEPENDENCE_BASE (arg1))
+                         && (TYPE_ALIGN (TREE_TYPE (arg0))
+                             == TYPE_ALIGN (TREE_TYPE (arg1)))))
                  && OP_SAME (0) && OP_SAME (1));
 
        case ARRAY_REF:
@@ -2962,7 +2973,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
             may have different types but same value here.  */
          if (!OP_SAME (0))
            return 0;
-         flags &= ~OEP_CONSTANT_ADDRESS_OF;
+         flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
          return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1),
                                       TREE_OPERAND (arg1, 1))
                   || OP_SAME (1))
@@ -2975,13 +2986,13 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
          if (!OP_SAME_WITH_NULL (0)
              || !OP_SAME (1))
            return 0;
-         flags &= ~OEP_CONSTANT_ADDRESS_OF;
+         flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
          return OP_SAME_WITH_NULL (2);
 
        case BIT_FIELD_REF:
          if (!OP_SAME (0))
            return 0;
-         flags &= ~OEP_CONSTANT_ADDRESS_OF;
+         flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
          return OP_SAME (1) && OP_SAME (2);
 
        default:
@@ -2992,6 +3003,10 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case ADDR_EXPR:
+         return operand_equal_p (TREE_OPERAND (arg0, 0),
+                                 TREE_OPERAND (arg1, 0),
+                                 flags | OEP_ADDRESS_OF);
+
        case TRUTH_NOT_EXPR:
          return OP_SAME (0);
 
index 8256fc3d9a6b499527f337e0091d7b612b01c4f1..a17c73f8f79abb9749d5549f5072486c59a41467 100644 (file)
@@ -1,3 +1,9 @@
+2015-03-09  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/65270
+       * gcc.dg/torture/pr65270-1.c: New testcase.
+       * gcc.dg/torture/pr65270-2.c: Likewise. 
+
 2015-03-09  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        PR tree-optimization/63743
diff --git a/gcc/testsuite/gcc.dg/torture/pr65270-1.c b/gcc/testsuite/gcc.dg/torture/pr65270-1.c
new file mode 100644 (file)
index 0000000..ae6dc3b
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+struct a 
+{
+  int a[100];
+};
+typedef struct a misaligned_t __attribute__ ((aligned (8)));
+typedef struct a aligned_t __attribute__ ((aligned (32)));
+
+__attribute__ ((used))
+__attribute__ ((noinline))
+void
+t(void *a, int misaligned, aligned_t *d)
+{
+  int i,v;
+  for (i=0;i<100;i++)
+    {
+      if (misaligned)
+       v=((misaligned_t *)a)->a[i];
+      else
+       v=((aligned_t *)a)->a[i];
+      d->a[i]+=v;
+    }
+}
+struct b {int v; misaligned_t m;aligned_t aa;} b;
+aligned_t d;
+int
+main()
+{
+  t(&b.m, 1, &d);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr65270-2.c b/gcc/testsuite/gcc.dg/torture/pr65270-2.c
new file mode 100644 (file)
index 0000000..d5b8f1c
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+
+struct a 
+{
+  int a[100];
+};
+typedef struct a misaligned_t __attribute__ ((aligned (8)));
+typedef struct a aligned_t __attribute__ ((aligned (32)));
+
+__attribute__ ((used))
+__attribute__ ((noinline))
+void
+t(void *a, int misaligned, aligned_t *d)
+{
+  int i,v;
+  for (i=0;i<100;i++)
+    d->a[i]+=!misaligned? ((aligned_t *)a)->a[i] : ((misaligned_t *)a)->a[i];
+}
+struct b {int v; misaligned_t m;aligned_t aa;} b;
+aligned_t d;
+int
+main()
+{
+  t(&b.m, 1, &d);
+  return 0;
+}
index 3aaf650ff73893fe194b8297396306d7d9bca008..ad1bb231ebef06a05fa2099bd627ca1678508e7d 100644 (file)
@@ -700,7 +700,8 @@ enum size_type_kind {
 enum operand_equal_flag {
   OEP_ONLY_CONST = 1,
   OEP_PURE_SAME = 2,
-  OEP_CONSTANT_ADDRESS_OF = 4
+  OEP_CONSTANT_ADDRESS_OF = 4,
+  OEP_ADDRESS_OF = 8
 };
 
 /* Enum and arrays used for tree allocation stats.