diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e01505f3282..a8359339684 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-10-13 Richard Biener + + PR tree-optimization/63419 + * gimple-fold.h (gimple_convert): New function. + * gimple-fold.c (gimple_convert): Likewise. + * tree-ssa-pre.c (create_expression_by_pieces): Use gimple_convert + to split out required conversions early. + 2014-10-13 Richard Sandiford * rtlanal.c (generic_subrtx_iterator ::add_subrtxes_to_queue): diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 76441c746bc..a0ce0db9766 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5295,3 +5295,20 @@ rewrite_to_defined_overflow (gimple stmt) return stmts; } + +/* Return OP converted to TYPE by emitting a conversion statement on SEQ + if required using location LOC. Note that OP will be returned + unmodified if GIMPLE does not require an explicit conversion between + its type and TYPE. */ + +tree +gimple_convert (gimple_seq *seq, location_t loc, tree type, tree op) +{ + if (useless_type_conversion_p (type, TREE_TYPE (op))) + return op; + op = fold_convert_loc (loc, type, op); + gimple_seq stmts = NULL; + op = force_gimple_operand (op, &stmts, true, NULL_TREE); + gimple_seq_add_seq_without_update (seq, stmts); + return op; +} diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index 9b4e4566a12..b55a3ef8b3e 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -45,4 +45,11 @@ extern tree gimple_fold_indirect_ref (tree); extern bool arith_code_with_undefined_signed_overflow (tree_code); extern gimple_seq rewrite_to_defined_overflow (gimple); +extern tree gimple_convert (gimple_seq *, location_t, tree, tree); +inline tree +gimple_convert (gimple_seq *seq, tree type, tree op) +{ + return gimple_convert (seq, UNKNOWN_LOCATION, type, op); +} + #endif /* GCC_GIMPLE_FOLD_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f34d55f8a75..1ab2f218049 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-10-13 Richard Biener + + PR tree-optimization/63419 + * g++.dg/torture/pr63419.C: New testcase. + 2014-10-12 Oleg Endo PR target/59401 diff --git a/gcc/testsuite/g++.dg/torture/pr63419.C b/gcc/testsuite/g++.dg/torture/pr63419.C new file mode 100644 index 00000000000..53f7c3e8c27 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr63419.C @@ -0,0 +1,225 @@ +// { dg-do compile } + +typedef float __m128 __attribute__ ((__vector_size__ (16))); +const int a = 0; +enum +{ + ReadOnlyAccessors +}; +template struct traits; +struct A +{ + enum + { + value = 1 + }; +}; +template struct EigenBase; +template class J; +template class DenseCoeffsBase; +template class K; +template class N; +template class CwiseUnaryOp; +template class L; +template class P; +template struct B; +template struct C; +template struct dense_xpr_base +{ + typedef N type; +}; +template void padd (Packet); +template <> struct C +{ + typedef __m128 type; +}; +struct D +{ + void + packetOp (C::type) + { + __m128 b = { m_other }; + padd (b); + } + float m_other; +}; +template +class DenseCoeffsBase : public EigenBase +{ +public: + typedef typename C::Scalar>::type PacketScalar; +}; +template +class DenseCoeffsBase + : public DenseCoeffsBase +{ +public: + template + void + copyPacket (typename traits::Index, J p2) + { + p2.derived ().template packet (0); + } +}; +template class J : public DenseCoeffsBase +{ +public: + using DenseCoeffsBase::derived; + template + Derived &lazyAssign (const J &); +}; +template class N : public J +{ +public: + template + typename B::Type operator*(N); + L array (); +}; +template struct EigenBase +{ + Derived + derived () const + { + return *static_cast (this); + } +}; +template struct F +{ + static void + run (Derived1 p1, Derived2 p2) + { + enum + { + srcAlignment + }; + for (;;) + p1.template copyPacket (0, p2); + } +}; +template +template +Derived & +J::lazyAssign (const J &p1) +{ + F::run (derived (), p1.derived ()); +} +template struct G +{ + static Derived + run (Derived p1, OtherDerived p2) + { + p1.lazyAssign (p2); + } +}; +class H +{ +public: + H (int, int, int); +}; +template class M : public dense_xpr_base::type +{ +public: + typedef typename traits::Index Index; + H m_storage; + M (Index, Index, Index) : m_storage (0, 0, 0) {} + template + void + _set_noalias (J p1) + { + G::run (this->derived (), p1.derived ()); + } +}; +template +struct traits > +{ + typedef _Scalar Scalar; + typedef int StorageKind; + typedef int Index; +}; +template +class K : public M > +{ +public: + typedef M Base; + typedef K Nested; + template K (T0, T1); + template K (N p1) : Base (0, 0, 0) + { + Base::_set_noalias (p1); + } +}; +template +struct traits > : traits +{ +}; +template class I; +template +class CwiseUnaryOp + : public I::StorageKind> +{ +public: + D + functor () + { + return m_functor; + } + typename XprType::Nested nestedExpression (); + D m_functor; +}; +template +class I + : public dense_xpr_base >::type +{ +public: + typedef CwiseUnaryOp Derived; + typedef typename dense_xpr_base >::type Base; + typedef Derived Nested; + using Base::derived; + template void packet (typename traits::Index) + { + derived ().functor ().packetOp ( + derived ().nestedExpression ().template packet (0)); + } +}; +template struct B +{ + typedef P > > > Type; +}; +template class O : public J +{ +public: + P matrix (); +}; +template +struct traits > : traits +{ +}; +template class L : public O > +{ +public: + typedef L Nested; + template + typename O::PacketScalar packet (typename traits::Index); +}; +template +struct traits > : traits +{ +}; +template class P : public N > +{ +public: + N

Base; + template void packet (typename traits

::Index) + { + m_expression.template packet (0); + } + ExpressionType m_expression; +}; +int +main () +{ + K m (0, 0); + K c (0, 0); + c = m.array ().matrix () * m; +} diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index a447c1e4f06..60ff70fa42b 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -2819,12 +2819,15 @@ create_expression_by_pieces (basic_block block, pre_expr expr, if (nary->opcode == POINTER_PLUS_EXPR) { if (i == 0) - genop[i] = fold_convert (nary->type, genop[i]); + genop[i] = gimple_convert (&forced_stmts, + nary->type, genop[i]); else if (i == 1) - genop[i] = convert_to_ptrofftype (genop[i]); + genop[i] = gimple_convert (&forced_stmts, + sizetype, genop[i]); } else - genop[i] = fold_convert (TREE_TYPE (nary->op[i]), genop[i]); + genop[i] = gimple_convert (&forced_stmts, + TREE_TYPE (nary->op[i]), genop[i]); } if (nary->opcode == CONSTRUCTOR) { @@ -2866,8 +2869,10 @@ create_expression_by_pieces (basic_block block, pre_expr expr, statements. We have to call unshare_expr because force_gimple_operand may modify the tree we pass to it. */ - folded = force_gimple_operand (unshare_expr (folded), &forced_stmts, + gimple_seq tem = NULL; + folded = force_gimple_operand (unshare_expr (folded), &tem, false, NULL); + gimple_seq_add_seq_without_update (&forced_stmts, tem); /* If we have any intermediate expressions to the value sets, add them to the value sets and chain them in the instruction stream. */