re PR rtl-optimization/78812 (Wrong code generation due to hoisting memory load acros...
authorJeff Law <law@redhat.com>
Thu, 5 Jan 2017 07:38:48 +0000 (00:38 -0700)
committerJeff Law <law@gcc.gnu.org>
Thu, 5 Jan 2017 07:38:48 +0000 (00:38 -0700)
PR tree-optimizatin/78812
* rtl.h (contains_mem_rtx_p): Prototype.
* ifcvt.c (containts_mem_rtx_p): Move from here to...
* rtlanal.c (contains_mem_rtx_p): Here and remvoe static linkage.
* gcse.c (prune_expressions): Use contains_mem_rtx_p to discover
and prune MEMs that are not at the toplevel of a SET_SRC rtx.  Look
through ZERO_EXTEND and SIGN_EXTEND when trying to avoid pruning
MEMs.

PR tree-optimization/78812
* g++.dg/torture/pr78812.C: New test.

From-SVN: r244093

gcc/ChangeLog
gcc/gcse.c
gcc/ifcvt.c
gcc/rtl.h
gcc/rtlanal.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr78812.C [new file with mode: 0644]

index ce11bc4ca0b2cff19e408c04f1f1bb57cae023e4..78b4412a0617c8799202a78fb08a49c1bff22cc3 100644 (file)
@@ -1,3 +1,14 @@
+2017-01-04  Jeff Law  <law@redhat.com>
+
+       PR tree-optimizatin/78812
+       * rtl.h (contains_mem_rtx_p): Prototype.
+       * ifcvt.c (containts_mem_rtx_p): Move from here to...
+       * rtlanal.c (contains_mem_rtx_p): Here and remvoe static linkage.
+       * gcse.c (prune_expressions): Use contains_mem_rtx_p to discover
+       and prune MEMs that are not at the toplevel of a SET_SRC rtx.  Look
+       through ZERO_EXTEND and SIGN_EXTEND when trying to avoid pruning
+       MEMs.
+
 2017-01-04  Alexandre Oliva <aoliva@redhat.com>
 
        * input.c (assert_char_at_range): Default-initialize
index fbc770a48dee7ec92022e1685f547d4e446b97eb..d28288df95c076ffeb5327d9609593536fb19b53 100644 (file)
@@ -1709,7 +1709,7 @@ prune_expressions (bool pre_p)
              continue;
            }
 
-         if (!pre_p && MEM_P (expr->expr))
+         if (!pre_p && contains_mem_rtx_p (expr->expr))
            /* Note memory references that can be clobbered by a call.
               We do not split abnormal edges in hoisting, so would
               a memory reference get hoisted along an abnormal edge,
@@ -1717,15 +1717,28 @@ prune_expressions (bool pre_p)
               constant memory references can be hoisted along abnormal
               edges.  */
            {
-             if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
-                 && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0)))
-               continue;
-
-             if (MEM_READONLY_P (expr->expr)
-                 && !MEM_VOLATILE_P (expr->expr)
-                 && MEM_NOTRAP_P (expr->expr))
-               /* Constant memory reference, e.g., a PIC address.  */
-               continue;
+             rtx x = expr->expr;
+
+             /* Common cases where we might find the MEM which may allow us
+                to avoid pruning the expression.  */
+             while (GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
+               x = XEXP (x, 0);
+
+             /* If we found the MEM, go ahead and look at it to see if it has
+                properties that allow us to avoid pruning its expression out
+                of the tables.  */
+             if (MEM_P (x))
+               {
+                 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+                     && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+                   continue;
+
+                 if (MEM_READONLY_P (x)
+                     && !MEM_VOLATILE_P (x)
+                     && MEM_NOTRAP_P (x))
+                   /* Constant memory reference, e.g., a PIC address.  */
+                   continue;
+               }
 
              /* ??? Optimally, we would use interprocedural alias
                 analysis to determine if this mem is actually killed
index 56c785e363228e07462594e1ba3f997f9103b542..68c1a1d42c406aa605aed7b8e3d92efd7bd43a9a 100644 (file)
@@ -3010,19 +3010,6 @@ noce_operand_ok (const_rtx op)
   return ! may_trap_p (op);
 }
 
-/* Return true if X contains a MEM subrtx.  */
-
-static bool
-contains_mem_rtx_p (rtx x)
-{
-  subrtx_iterator::array_type array;
-  FOR_EACH_SUBRTX (iter, array, x, ALL)
-    if (MEM_P (*iter))
-      return true;
-
-  return false;
-}
-
 /* Return true iff basic block TEST_BB is valid for noce if-conversion.
    The condition used in this if-conversion is in COND.
    In practice, check that TEST_BB ends with a single set
index 302afc0d1b032f97c55d9b5864b5d31017022829..b9a7989c0d7e621aa2e657802920aa5a50413d05 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3090,6 +3090,7 @@ extern bool rtx_referenced_p (const_rtx, const_rtx);
 extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **);
 extern int computed_jump_p (const rtx_insn *);
 extern bool tls_referenced_p (const_rtx);
+extern bool contains_mem_rtx_p (rtx x);
 
 /* Overload for refers_to_regno_p for checking a single register.  */
 inline bool
index ef93584449d0a0312dbe3cb86f8076c5ae43fb6d..acb4230aac83eb9dd0e608349e51197dae66539c 100644 (file)
@@ -685,6 +685,19 @@ rtx_addr_can_trap_p (const_rtx x)
   return rtx_addr_can_trap_p_1 (x, 0, 0, VOIDmode, false);
 }
 
+/* Return true if X contains a MEM subrtx.  */
+
+bool
+contains_mem_rtx_p (rtx x)
+{
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
+    if (MEM_P (*iter))
+      return true;
+
+  return false;
+}
+
 /* Return true if X is an address that is known to not be zero.  */
 
 bool
index 74e8d0dab3c328093296864b63e31a372e61a4d6..16b27e61d6f8c44049cad2916beb6e92390ed41c 100644 (file)
@@ -1,3 +1,8 @@
+2017-01-04  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/78812
+       * g++.dg/torture/pr78812.C: New test.
+
 2017-01-04  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        PR target/71977
diff --git a/gcc/testsuite/g++.dg/torture/pr78812.C b/gcc/testsuite/g++.dg/torture/pr78812.C
new file mode 100644 (file)
index 0000000..efe0936
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-do run } 
+// { dg-options "-fpic" { target fpic } }
+
+struct T
+{
+  bool a;
+  T () : a (false) {}
+  ~T () { if (!a) __builtin_abort (); }
+};
+
+__attribute__((noinline))
+void
+test (T &x)
+{
+  x.a = true;
+}
+
+int
+main ()
+{
+  T T;
+  test (T);
+}
+