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