re PR middle-end/49519 (Revision 175272 miscompiled 447.dealII in SPEC CPU 2006)
authorKirill Yukhin <kirill.yukhin@intel.com>
Fri, 8 Jul 2011 13:12:03 +0000 (13:12 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Fri, 8 Jul 2011 13:12:03 +0000 (06:12 -0700)
Fix PR middle-end/49519.

gcc/

2011-07-08  Kirill Yukhin  <kirill.yukhin@intel.com>

PR middle-end/49519
* calls.c (mem_overlaps_already_clobbered_arg_p): Additional
check if address is stored in register. If so - give up.
(check_sibcall_argument_overlap_1): Do not perform check of
overlapping when it is call to address.

gcc/tessuite/

2011-07-08  Kirill Yukhin  <kirill.yukhin@intel.com>

PR middle-end/49519
* g++.dg/torture/pr49519.C: New test.

From-SVN: r176042

gcc/ChangeLog
gcc/calls.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr49519.C [new file with mode: 0644]

index 6a9d81a4890b7c380b684222ea43e2b3a716899c..8112a8cce285f8ab3e40f97060b442b0412daef1 100644 (file)
@@ -1,3 +1,11 @@
+2011-07-08  Kirill Yukhin  <kirill.yukhin@intel.com>
+
+       PR middle-end/49519
+       * calls.c (mem_overlaps_already_clobbered_arg_p): Additional
+       check if address is stored in register. If so - give up.
+       (check_sibcall_argument_overlap_1): Do not perform check of
+       overlapping when it is call to address.
+
 2011-07-08  Georg-Johann Lay  <avr@gjlay.de>
        
        * config/avr/avr.c (output_reload_insisf): Use 'REG_Z+1' instead
index 7538e4e5040899bd9806187c715e1a66c0144f6f..0cd8cc9dbcb9d2e26032461ac18c6137e70c85d5 100644 (file)
@@ -1591,6 +1591,10 @@ mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
           && (XEXP (addr, 0) == crtl->args.internal_arg_pointer
               || XEXP (addr, 1) == crtl->args.internal_arg_pointer))
     return true;
+  /* If the address comes in a register, we have no idea of its origin so
+     give up and conservatively return true.  */
+  else if (REG_P(addr))
+    return true;
   else
     return false;
 
@@ -1831,6 +1835,10 @@ check_sibcall_argument_overlap_1 (rtx x)
 
   code = GET_CODE (x);
 
+  /* We need not check the operands of the CALL expression itself.  */
+  if (code == CALL)
+    return 0;
+
   if (code == MEM)
     return mem_overlaps_already_clobbered_arg_p (XEXP (x, 0),
                                                 GET_MODE_SIZE (GET_MODE (x)));
index 93d7c826f630a0fad6e6fc5b3d2f7faf71711839..360c0aae53d7cbb5ab4b9d623b2ec66e1afe2e5b 100644 (file)
@@ -1,3 +1,8 @@
+2011-07-08  Kirill Yukhin  <kirill.yukhin@intel.com>
+
+       PR middle-end/49519
+       * g++.dg/torture/pr49519.C: New test.
+
 2011-07-08  Martin Jambor  <mjambor@suse.cz>
 
        * gcc.dg/tree-ssa/sra-12.c: Skip dump scan on avr targets.
diff --git a/gcc/testsuite/g++.dg/torture/pr49519.C b/gcc/testsuite/g++.dg/torture/pr49519.C
new file mode 100644 (file)
index 0000000..2888709
--- /dev/null
@@ -0,0 +1,135 @@
+/* { dg-do run } */
+
+#include <stdlib.h>
+
+struct null_type {};
+
+inline const null_type cnull() { return null_type(); }
+
+template <class TT> struct cons;
+class tuple;
+
+template< int N >
+struct get_class {
+  template<class TT >
+  inline static int& get(cons<TT>& t)
+  {
+    return get_class<N-1>::template get(t.tail);
+  }
+};
+
+template<>
+struct get_class<0> {
+  template<class TT>
+  inline static int& get(cons<TT>& t)
+  {
+    return t.head;
+  }
+};
+
+template<int N, class T>
+struct element
+{
+private:
+  typedef typename T::tail_type Next;
+public:
+  typedef typename element<N-1, Next>::type type;
+};
+
+template<class T>
+struct element<0,T>
+{
+  typedef int type;
+};
+
+template<int N, class TT>
+inline int& get(cons<TT>& c) {
+  return get_class<N>::template get(c);
+}
+
+template <class TT>
+struct cons {
+  typedef TT tail_type;
+
+  int head;
+  tail_type tail;
+
+  cons() : head(), tail() {}
+
+  template <class T1, class T2, class T3, class T4>
+  cons( T1& t1, T2& t2, T3& t3, T4& t4 )
+    : head (t1),
+      tail (t2, t3, t4, cnull())
+      {}
+};
+
+template <>
+struct cons<null_type> {
+  typedef null_type tail_type;
+
+  int head;
+
+  cons() : head() {}
+
+  template<class T1>
+  cons(T1& t1, const null_type&, const null_type&, const null_type&)
+  : head (t1) {}
+};
+
+template <class T0, class T1, class T2, class T3>
+struct map_tuple_to_cons
+{
+  typedef cons<typename map_tuple_to_cons<T1, T2, T3, null_type>::type> type;
+};
+
+template <>
+struct map_tuple_to_cons<null_type, null_type, null_type, null_type>
+{
+  typedef null_type type;
+};
+
+class tuple :
+  public map_tuple_to_cons<int, int, int, int>::type
+{
+public:
+  typedef typename
+    map_tuple_to_cons<int, int, int, int>::type inherited;
+
+  tuple(const int &t0,
+        const int &t1,
+        const int &t2,
+        const int &t3)
+    : inherited(t0, t1, t2, t3) {}
+};
+
+void foo(void (*boo)(int, int, int, int), tuple t)
+{
+  boo(get<0>(t), get<1>(t), get<2>(t), get<3>(t));
+}
+
+int tailcalled_t1;
+int tailcalled_t2;
+int tailcalled_t3;
+int tailcalled_t4;
+
+void print(int t1, int t2, int t3, int t4)
+{
+  tailcalled_t1 = t1;
+  tailcalled_t2 = t2;
+  tailcalled_t3 = t3;
+  tailcalled_t4 = t4;
+}
+
+int main ()
+{
+  tuple t(1,2,3,4);
+  foo(print, t);
+
+  if( (get<0>(t) != tailcalled_t1)
+    ||(get<1>(t) != tailcalled_t2)
+    ||(get<2>(t) != tailcalled_t3)
+      ||(get<3>(t) != tailcalled_t4))
+      abort();
+
+  return 0;
+}