1 /* { dg-do compile } */
2 /* { dg-options "-O2 -fdump-tree-optimized" } */
3 extern void __assert_fail(const char*, const char*, int, const char*);
4 namespace Eigen {
5 enum { AutoAlign };
6 template <int, typename>
7 struct conditional;
8 template <typename Else>
9 struct conditional<false, Else> {
10   typedef Else type;
11 };
12 template <typename T>
13 struct remove_reference {
14   typedef T type;
15 };
16 struct is_arithmetic {
17   enum { value };
18 };
19 template <typename>
20 struct traits;
21 template <typename T>
22 struct traits<const T> : traits<T> {};
23 template <typename>
24 struct evaluator;
25 template <typename>
26 struct EigenBase;
27 template <typename>
28 class PlainObjectBase;
29 template <typename, int _Rows, int _Cols, int = AutoAlign, int = _Rows,
30           int = _Cols>
31 class Matrix;
32 template <typename>
33 class MatrixBase;
34 template <typename, typename>
35 class CwiseNullaryOp;
36 template <typename, typename, typename>
37 class CwiseBinaryOp;
38 template <typename>
39 struct scalar_constant_op;
40 template <int _Rows>
41 struct size_at_compile_time {
42   enum { ret = _Rows };
43 };
44 struct ref_selector {
45   typedef const Matrix<float, 3, 1>& type;
46 };
47 template <typename Derived>
48 struct dense_xpr_base {
49   typedef MatrixBase<Derived> type;
50 };
51 template <typename Derived, typename = typename traits<Derived>::XprKind>
52 struct generic_xpr_base {
53   typedef typename dense_xpr_base<Derived>::type type;
54 };
55 template <typename Expr, typename Scalar = typename Expr::Scalar>
56 struct plain_constant_type {
57   ;
58   typedef CwiseNullaryOp<scalar_constant_op<Scalar>,
59                          Matrix<Scalar, traits<Expr>::ColsAtCompileTime,
60                                 traits<Expr>::MaxRowsAtCompileTime,
61                                 traits<Expr>::MaxColsAtCompileTime>>
62       type;
63 };
64 struct scalar_product_op {
65   float operator()(float a, float b) { return a * b; }
66 };
67 template <typename>
68 struct scalar_constant_op {
69   scalar_constant_op(float other) : m_other(other) {}
70   float operator()() { return m_other; }
71   float m_other;
72 };
73 struct assign_op {
74   void assignCoeff(float& a, float b) { a = b; }
75 };
76 template <typename Derived>
77 class DenseCoeffsBase : public EigenBase<Derived> {
78  public:
79   typedef typename traits<Derived>::Scalar Scalar;
80   typedef
81       typename conditional<is_arithmetic::value, Scalar>::type CoeffReturnType;
82 };
83 template <typename Derived>
84 class DenseBase : public DenseCoeffsBase<Derived> {
85  public:
86   enum {
87     RowsAtCompileTime = traits<Derived>::RowsAtCompileTime,
88     SizeAtCompileTime = size_at_compile_time<RowsAtCompileTime>::ret,
89     MaxSizeAtCompileTime
90   };
91 };
92 template <typename Derived>
93 class MatrixBase : public DenseBase<Derived> {
94  public:
95   using DenseBase<Derived>::derived;
96   template <typename T>
97   CwiseBinaryOp<scalar_product_op, const Derived,
98                 const typename plain_constant_type<Derived, T>::type>
99   operator*(T& scalar) {
100     return CwiseBinaryOp<scalar_product_op, const Derived,
101                          const typename plain_constant_type<Derived>::type>(
102         derived(), typename plain_constant_type<Derived>::type(derived().rows(),
103                                                                0, scalar));
104   }
105 };
106 template <typename Derived>
107 struct EigenBase {
108   const Derived& derived() const { return *static_cast<const Derived*>(this); }
109   Derived& const_cast_derived() const {
110     return *static_cast<Derived*>(const_cast<EigenBase*>(this));
111   }
112 };
113 template <typename>
114 struct binary_evaluator;
115 template <typename T>
116 struct evaluator<const T> : evaluator<T> {
117   evaluator(const T& xpr) : evaluator<T>(xpr) {}
118 };
119 template <typename Derived>
120 struct evaluator {
121   typedef Derived PlainObjectType;
122   typedef typename PlainObjectType::Scalar Scalar;
123   evaluator(const PlainObjectType& m) : m_data(m.data()) {}
124   typename PlainObjectType::CoeffReturnType coeff(long row, long) {
125     return m_data[row];
126   }
127   Scalar& coeffRef(long row, long) { return const_cast<Scalar*>(m_data)[row]; }
128   const Scalar* m_data;
129 };
130 template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
131           int MaxCols>
132 struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
133     : evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols>>> {
134   typedef Matrix<Scalar, Rows, Cols> XprType;
135   evaluator(const XprType& m) : evaluator<PlainObjectBase<XprType>>(m) {}
136 };
137 struct nullary_wrapper {
138   template <typename IndexType>
139   float operator()(scalar_constant_op<float> op, IndexType, IndexType) const {
140     return op();
141   }
142 };
143 template <typename NullaryOp, typename PlainObjectType>
144 struct evaluator<CwiseNullaryOp<NullaryOp, PlainObjectType>> {
145   typedef CwiseNullaryOp<NullaryOp, PlainObjectType> XprType;
146   evaluator(XprType n) : m_functor(n.functor()) {}
147   template <typename IndexType>
148   typename XprType::CoeffReturnType coeff(IndexType row, IndexType col) {
149     return m_wrapper(m_functor, row, col);
150   }
151   NullaryOp m_functor;
152   nullary_wrapper m_wrapper;
153 };
154 template <typename BinaryOp, typename Lhs, typename Rhs>
155 struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>>
156     : binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> {
157   evaluator(CwiseBinaryOp<BinaryOp, Lhs, Rhs> xpr)
158       : binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>>(xpr) {}
159 };
160 template <typename BinaryOp, typename Lhs, typename Rhs>
161 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> {
162   typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
163   binary_evaluator(XprType xpr) : m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {}
164   typename XprType::CoeffReturnType coeff(long row, long col) {
165     return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col));
166   }
167   BinaryOp m_functor;
168   evaluator<Lhs> m_lhsImpl;
169   evaluator<Rhs> m_rhsImpl;
170 };
171 template <typename Kernel, int Index, int Stop>
172 struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling {
173   enum { outer, inner = Index };
174   static void run(Kernel kernel) {
175     kernel.assignCoeffByOuterInner(outer, inner);
176     copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Index + 1,
177                                                             Stop>::run(kernel);
178   }
179 };
180 template <typename Kernel, int Stop>
181 struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Stop,
182                                                                Stop> {
183   static void run(Kernel) {}
184 };
185 template <typename Kernel>
186 struct dense_assignment_loop {
187   static void run(Kernel kernel) {
188     typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
189     enum { size = DstXprType::SizeAtCompileTime, alignedSize = 0 };
190     copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, alignedSize,
191                                                             size>::run(kernel);
192   }
193 };
194 template <typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT,
195           typename Functor>
196 class generic_dense_assignment_kernel {
197   typedef typename DstEvaluatorTypeT::XprType DstXprType;
198 
199  public:
200   typedef DstEvaluatorTypeT DstEvaluatorType;
201   typedef SrcEvaluatorTypeT SrcEvaluatorType;
202   generic_dense_assignment_kernel(DstEvaluatorType dst, SrcEvaluatorType src,
203                                   Functor, DstXprType& dstExpr)
204       : m_dst(dst), m_src(src), m_dstExpr(dstExpr) {}
205   long assignCoeff_col;
206   void assignCoeffByOuterInner(long, long inner) {
207     long __trans_tmp_1 = inner;
208     m_functor.assignCoeff(m_dst.coeffRef(__trans_tmp_1, assignCoeff_col),
209                           m_src.coeff(__trans_tmp_1, assignCoeff_col));
210   }
211   DstEvaluatorType m_dst;
212   SrcEvaluatorType m_src;
213   Functor m_functor;
214   DstXprType& m_dstExpr;
215 };
216 template <typename DstXprType, typename SrcXprType, typename Functor>
217 void call_dense_assignment_loop(DstXprType& dst, SrcXprType src, Functor func) {
218   typedef evaluator<DstXprType> DstEvaluatorType;
219   typedef evaluator<SrcXprType> SrcEvaluatorType;
220   SrcEvaluatorType srcEvaluator(src);
221   DstEvaluatorType dstEvaluator(dst);
222   typedef generic_dense_assignment_kernel<DstEvaluatorType, SrcEvaluatorType,
223                                           Functor>
224       Kernel;
225   Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
226   dense_assignment_loop<Kernel>::run(kernel);
227 }
228 template <typename Dst, typename Src, typename Func>
229 void call_assignment_no_alias(Dst& dst, Src src, Func func) {
230   enum { NeedToTranspose };
231   typename conditional<NeedToTranspose, Dst&>::type actualDst(dst);
232   CwiseBinaryOp<scalar_product_op, const Matrix<float, 3, 1>,
233                 const CwiseNullaryOp<scalar_constant_op<float>,
234                                      const Matrix<float, 3, 1, 0, 2, 3>>>
235       __trans_tmp_4 = src;
236   call_dense_assignment_loop(actualDst, __trans_tmp_4, func);
237 }
238 template <int Size>
239 struct plain_array {
240   float array[Size];
241 };
242 template <int Size, int _Rows>
243 class DenseStorage {
244   plain_array<Size> m_data;
245 
246  public:
247   DenseStorage() {}
248   DenseStorage(const DenseStorage&);
249   static long rows() { return _Rows; }
250   const float* data() const { return m_data.array; }
251   float* data() { return m_data.array; }
252 };
253 template <typename Derived>
254 class PlainObjectBase : public dense_xpr_base<Derived>::type {
255  public:
256   typedef typename dense_xpr_base<Derived>::type Base;
257   typedef typename traits<Derived>::Scalar Scalar;
258   DenseStorage<Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime> m_storage;
259   long rows() const { return m_storage.rows(); }
260   const Scalar* data() const { return m_storage.data(); }
261   PlainObjectBase() {}
262   template <typename OtherDerived>
263   PlainObjectBase(const DenseBase<OtherDerived>& other) {
264     _set_noalias(other);
265   }
266   template <typename OtherDerived>
267   void _set_noalias(const DenseBase<OtherDerived>& other) {
268     call_assignment_no_alias(this->derived(), other.derived(), assign_op());
269   }
270 };
271 template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
272           int _MaxCols>
273 struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> {
274   typedef _Scalar Scalar;
275   typedef int XprKind;
276   enum {
277     RowsAtCompileTime = _Rows,
278     ColsAtCompileTime,
279     MaxRowsAtCompileTime,
280     MaxColsAtCompileTime,
281   };
282 };
283 template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
284           int _MaxCols>
285 class Matrix
286     : public PlainObjectBase<
287           Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> {
288  public:
289   typedef PlainObjectBase<Matrix> Base;
290   typedef typename traits<Matrix>::Scalar Scalar;
291   Matrix(Scalar& x, Scalar& y, Scalar& z) {
292     m_storage.data()[0] = x;
293     m_storage.data()[1] = y;
294     m_storage.data()[2] = z;
295   }
296   template <typename OtherDerived>
297   Matrix(const EigenBase<OtherDerived>& other) : Base(other.derived()) {}
298   using Base::m_storage;
299 };
300 template <typename BinaryOp, typename Lhs, typename Rhs>
301 struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> {
302   typedef typename traits<Lhs>::XprKind XprKind;
303   enum { RowsAtCompileTime };
304   typedef float Scalar;
305 };
306 template <typename>
307 class CwiseBinaryOpImpl;
308 template <typename, typename, typename RhsType>
309 class CwiseBinaryOp : public CwiseBinaryOpImpl<RhsType> {
310  public:
311   typedef ref_selector::type LhsNested;
312   typedef RhsType RhsNested;
313   CwiseBinaryOp(const Matrix<float, 3, 1>& aLhs, RhsType& aRhs)
314       : m_lhs(aLhs), m_rhs(aRhs) {}
315   remove_reference<LhsNested>::type& lhs() { return m_lhs; }
316   typename remove_reference<RhsNested>::type& rhs() { return m_rhs; }
317   LhsNested m_lhs;
318   RhsNested m_rhs;
319 };
320 template <typename>
321 class CwiseBinaryOpImpl
322     : public generic_xpr_base<CwiseBinaryOp<
323           scalar_product_op, const Matrix<float, 3, 1>,
324           const CwiseNullaryOp<scalar_constant_op<float>,
325                                const Matrix<float, 3, 1, 0, 2, 3>>>>::type {};
326 template <typename NullaryOp, typename PlainObjectType>
327 struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType>>
328     : traits<PlainObjectType> {};
329 template <typename, typename PlainObjectType>
330 class CwiseNullaryOp
331     : public dense_xpr_base<CwiseNullaryOp<int, PlainObjectType>>::type {
332  public:
333   CwiseNullaryOp(long rows, long, scalar_constant_op<float> func)
334       : m_functor(func) {
335     rows ? void() : __assert_fail("", "", 1, __PRETTY_FUNCTION__);
336   }
337   scalar_constant_op<float> functor() { return m_functor; }
338   scalar_constant_op<float> m_functor;
339 };
340 }  // namespace Eigen
341 Eigen::Matrix<float, 3, 1> should_inline(float x, float y, float z,
342                                          float scale) {
343   return Eigen::Matrix<float, 3, 1>(x, y, z) * scale;
344 }
345 
346 // We should inline everything to should_inline
347 
348 /* { dg-final { scan-tree-dump-times "Function" "optimized" } } */
349