Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard.
2015-01-16 Richard Biener <rguent...@suse.de> PR tree-optimization/64568 * tree-ssa-forwprop.c (pass_forwprop::execute): Guard complex load rewriting for TARGET_MEM_REFs. * g++.dg/torture/pr64568-2.C: New testcase. Index: gcc/tree-ssa-forwprop.c =================================================================== --- gcc/tree-ssa-forwprop.c (revision 219724) +++ gcc/tree-ssa-forwprop.c (working copy) @@ -2230,6 +2230,8 @@ pass_forwprop::execute (function *fun) else if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE && gimple_assign_load_p (stmt) && !gimple_has_volatile_ops (stmt) + && (TREE_CODE (gimple_assign_rhs1 (stmt)) + != TARGET_MEM_REF) && !stmt_can_throw_internal (stmt)) { /* Rewrite loads used only in real/imagpart extractions to Index: gcc/testsuite/g++.dg/torture/pr64568-2.C =================================================================== --- gcc/testsuite/g++.dg/torture/pr64568-2.C (revision 0) +++ gcc/testsuite/g++.dg/torture/pr64568-2.C (working copy) @@ -0,0 +1,146 @@ +// { dg-do compile } + +namespace std +{ + typedef __SIZE_TYPE__ size_t; +} +class H; +namespace std +{ + template <typename> struct complex; + template <typename _Tp> + complex<_Tp> operator+(complex<_Tp> &__x, complex<_Tp> __y) + { + complex<_Tp> a = __x; + a += __y; + return a; + } + template <> struct complex<double> + { + int + imag () + { + return __imag__ _M_value; + } + void operator+=(complex __z) { _M_value += _M_value; _M_value += __z.imag (); } + _Complex double _M_value; + }; +} +struct A +{ + typedef std::complex<double> &const_reference; +}; +class B +{ +public: + B (int); + std::complex<double> &operator[](int i) { return data_[i]; } + std::complex<double> *data_; +}; +struct C +{ + static std::complex<double> + apply (A::const_reference t1, std::complex<double> t2) + { + return t1 + t2; + } + typedef std::complex<double> result_type; +}; +template <class T1, class> struct D +{ + static void + apply (T1 t1, std::complex<double> t2) + { + t1 = t2; + } +}; +class ublas_expression +{ +public: + ~ublas_expression (); +}; +template <class> class F +{ +}; +template <class E> class matrix_expression : ublas_expression +{ +public: + E &operator()() {} +}; +class I : public F<int> +{ +public: + typedef int value_type; + I (int); +}; +template <class E1, class E2> matrix_expression<int> outer_prod (F<E1>, F<E2>); +template <class E1, class F> class J : public matrix_expression<J<E1, F> > +{ +public: + typedef typename F::result_type value_type; + value_type operator()(int i, int) + { + return F::apply (e1_ (i, 0), e2_ (0, 0)); + } + E1 e1_; + E1 e2_; +}; +template <class E1, class E2> +J<H, C> operator+(matrix_expression<E1>, matrix_expression<E2>); +template <template <class, class> class F, class M, class E> +void +indexing_matrix_assign (M m, matrix_expression<E> e, int) +{ + for (int i; i; ++i) + F<typename M::reference, typename E::value_type>::apply (m (0, 0), + e ()(i, 0)); +} +template <template <class, class> class F, class, class M, class E, class C> +void +matrix_assign (M m, matrix_expression<E> e, int, C) +{ + indexing_matrix_assign<F> (m, e, 0); +} +template <template <class, class> class F, class M, class E> +void +matrix_assign (M m, matrix_expression<E> e) +{ + matrix_assign<F, int> (m, e, 0, typename M::orientation_category ()); +} +class H : matrix_expression<int> +{ +public: + typedef std::complex<double> &reference; + typedef int orientation_category; + H (int, int) : data_ (0) {} + template <class AE> H (matrix_expression<AE> ae) : data_ (0) + { + matrix_assign<D> (*this, ae); + } + B & + data () + { + } + std::complex<double> &operator()(int i, int) { return data ()[i]; } + void operator+=(matrix_expression ae) { H (*this + ae); } + B data_; +}; +template <class M, class T, class V1, class V2> +void +sr2 (M m, T, V1 v1, V2 v2) +{ + m += outer_prod (v2, v1); +} +template <class, class, std::size_t> struct G +{ + void test (); +}; +template struct G<I, H, 3>; +template <class V, class M, std::size_t N> +void +G<V, M, N>::test () +{ + V b (0), c (0); + M m (0, 0); + sr2 (m, typename V::value_type (), b, c); +}