From 6c3cb698c53a85548621eeb871011b6d7774051c Mon Sep 17 00:00:00 2001 From: Kirill Yukhin Date: Fri, 8 Jul 2011 13:12:03 +0000 Subject: [PATCH] re PR middle-end/49519 (Revision 175272 miscompiled 447.dealII in SPEC CPU 2006) Fix PR middle-end/49519. gcc/ 2011-07-08 Kirill Yukhin 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 PR middle-end/49519 * g++.dg/torture/pr49519.C: New test. From-SVN: r176042 --- gcc/ChangeLog | 8 ++ gcc/calls.c | 8 ++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/torture/pr49519.C | 135 +++++++++++++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 gcc/testsuite/g++.dg/torture/pr49519.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6a9d81a4890..8112a8cce28 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2011-07-08 Kirill Yukhin + + 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 * config/avr/avr.c (output_reload_insisf): Use 'REG_Z+1' instead diff --git a/gcc/calls.c b/gcc/calls.c index 7538e4e5040..0cd8cc9dbcb 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -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))); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 93d7c826f63..360c0aae53d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-07-08 Kirill Yukhin + + PR middle-end/49519 + * g++.dg/torture/pr49519.C: New test. + 2011-07-08 Martin Jambor * 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 index 00000000000..2888709d99f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr49519.C @@ -0,0 +1,135 @@ +/* { dg-do run } */ + +#include + +struct null_type {}; + +inline const null_type cnull() { return null_type(); } + +template struct cons; +class tuple; + +template< int N > +struct get_class { + template + inline static int& get(cons& t) + { + return get_class::template get(t.tail); + } +}; + +template<> +struct get_class<0> { + template + inline static int& get(cons& t) + { + return t.head; + } +}; + +template +struct element +{ +private: + typedef typename T::tail_type Next; +public: + typedef typename element::type type; +}; + +template +struct element<0,T> +{ + typedef int type; +}; + +template +inline int& get(cons& c) { + return get_class::template get(c); +} + +template +struct cons { + typedef TT tail_type; + + int head; + tail_type tail; + + cons() : head(), tail() {} + + template + cons( T1& t1, T2& t2, T3& t3, T4& t4 ) + : head (t1), + tail (t2, t3, t4, cnull()) + {} +}; + +template <> +struct cons { + typedef null_type tail_type; + + int head; + + cons() : head() {} + + template + cons(T1& t1, const null_type&, const null_type&, const null_type&) + : head (t1) {} +}; + +template +struct map_tuple_to_cons +{ + typedef cons::type> type; +}; + +template <> +struct map_tuple_to_cons +{ + typedef null_type type; +}; + +class tuple : + public map_tuple_to_cons::type +{ +public: + typedef typename + map_tuple_to_cons::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; +} -- 2.30.2