Add testcase for PR98265
gcc/testsuite/ChangeLog: 2021-04-01 Jan Hubicka <hubicka@ucw.cz> PR ipa/98265 * gcc.dg/tree-ssa/pr98265.C: New test.
This commit is contained in:
parent
7b478ede2a
commit
3064fc21aa
1 changed files with 348 additions and 0 deletions
348
gcc/testsuite/gcc.dg/tree-ssa/pr98265.C
Normal file
348
gcc/testsuite/gcc.dg/tree-ssa/pr98265.C
Normal file
|
@ -0,0 +1,348 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
extern void __assert_fail(const char*, const char*, int, const char*);
|
||||
namespace Eigen {
|
||||
enum { AutoAlign };
|
||||
template <int, typename>
|
||||
struct conditional;
|
||||
template <typename Else>
|
||||
struct conditional<false, Else> {
|
||||
typedef Else type;
|
||||
};
|
||||
template <typename T>
|
||||
struct remove_reference {
|
||||
typedef T type;
|
||||
};
|
||||
struct is_arithmetic {
|
||||
enum { value };
|
||||
};
|
||||
template <typename>
|
||||
struct traits;
|
||||
template <typename T>
|
||||
struct traits<const T> : traits<T> {};
|
||||
template <typename>
|
||||
struct evaluator;
|
||||
template <typename>
|
||||
struct EigenBase;
|
||||
template <typename>
|
||||
class PlainObjectBase;
|
||||
template <typename, int _Rows, int _Cols, int = AutoAlign, int = _Rows,
|
||||
int = _Cols>
|
||||
class Matrix;
|
||||
template <typename>
|
||||
class MatrixBase;
|
||||
template <typename, typename>
|
||||
class CwiseNullaryOp;
|
||||
template <typename, typename, typename>
|
||||
class CwiseBinaryOp;
|
||||
template <typename>
|
||||
struct scalar_constant_op;
|
||||
template <int _Rows>
|
||||
struct size_at_compile_time {
|
||||
enum { ret = _Rows };
|
||||
};
|
||||
struct ref_selector {
|
||||
typedef const Matrix<float, 3, 1>& type;
|
||||
};
|
||||
template <typename Derived>
|
||||
struct dense_xpr_base {
|
||||
typedef MatrixBase<Derived> type;
|
||||
};
|
||||
template <typename Derived, typename = typename traits<Derived>::XprKind>
|
||||
struct generic_xpr_base {
|
||||
typedef typename dense_xpr_base<Derived>::type type;
|
||||
};
|
||||
template <typename Expr, typename Scalar = typename Expr::Scalar>
|
||||
struct plain_constant_type {
|
||||
;
|
||||
typedef CwiseNullaryOp<scalar_constant_op<Scalar>,
|
||||
Matrix<Scalar, traits<Expr>::ColsAtCompileTime,
|
||||
traits<Expr>::MaxRowsAtCompileTime,
|
||||
traits<Expr>::MaxColsAtCompileTime>>
|
||||
type;
|
||||
};
|
||||
struct scalar_product_op {
|
||||
float operator()(float a, float b) { return a * b; }
|
||||
};
|
||||
template <typename>
|
||||
struct scalar_constant_op {
|
||||
scalar_constant_op(float other) : m_other(other) {}
|
||||
float operator()() { return m_other; }
|
||||
float m_other;
|
||||
};
|
||||
struct assign_op {
|
||||
void assignCoeff(float& a, float b) { a = b; }
|
||||
};
|
||||
template <typename Derived>
|
||||
class DenseCoeffsBase : public EigenBase<Derived> {
|
||||
public:
|
||||
typedef typename traits<Derived>::Scalar Scalar;
|
||||
typedef
|
||||
typename conditional<is_arithmetic::value, Scalar>::type CoeffReturnType;
|
||||
};
|
||||
template <typename Derived>
|
||||
class DenseBase : public DenseCoeffsBase<Derived> {
|
||||
public:
|
||||
enum {
|
||||
RowsAtCompileTime = traits<Derived>::RowsAtCompileTime,
|
||||
SizeAtCompileTime = size_at_compile_time<RowsAtCompileTime>::ret,
|
||||
MaxSizeAtCompileTime
|
||||
};
|
||||
};
|
||||
template <typename Derived>
|
||||
class MatrixBase : public DenseBase<Derived> {
|
||||
public:
|
||||
using DenseBase<Derived>::derived;
|
||||
template <typename T>
|
||||
CwiseBinaryOp<scalar_product_op, const Derived,
|
||||
const typename plain_constant_type<Derived, T>::type>
|
||||
operator*(T& scalar) {
|
||||
return CwiseBinaryOp<scalar_product_op, const Derived,
|
||||
const typename plain_constant_type<Derived>::type>(
|
||||
derived(), typename plain_constant_type<Derived>::type(derived().rows(),
|
||||
0, scalar));
|
||||
}
|
||||
};
|
||||
template <typename Derived>
|
||||
struct EigenBase {
|
||||
const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
Derived& const_cast_derived() const {
|
||||
return *static_cast<Derived*>(const_cast<EigenBase*>(this));
|
||||
}
|
||||
};
|
||||
template <typename>
|
||||
struct binary_evaluator;
|
||||
template <typename T>
|
||||
struct evaluator<const T> : evaluator<T> {
|
||||
evaluator(const T& xpr) : evaluator<T>(xpr) {}
|
||||
};
|
||||
template <typename Derived>
|
||||
struct evaluator {
|
||||
typedef Derived PlainObjectType;
|
||||
typedef typename PlainObjectType::Scalar Scalar;
|
||||
evaluator(const PlainObjectType& m) : m_data(m.data()) {}
|
||||
typename PlainObjectType::CoeffReturnType coeff(long row, long) {
|
||||
return m_data[row];
|
||||
}
|
||||
Scalar& coeffRef(long row, long) { return const_cast<Scalar*>(m_data)[row]; }
|
||||
const Scalar* m_data;
|
||||
};
|
||||
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
|
||||
int MaxCols>
|
||||
struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
|
||||
: evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols>>> {
|
||||
typedef Matrix<Scalar, Rows, Cols> XprType;
|
||||
evaluator(const XprType& m) : evaluator<PlainObjectBase<XprType>>(m) {}
|
||||
};
|
||||
struct nullary_wrapper {
|
||||
template <typename IndexType>
|
||||
float operator()(scalar_constant_op<float> op, IndexType, IndexType) const {
|
||||
return op();
|
||||
}
|
||||
};
|
||||
template <typename NullaryOp, typename PlainObjectType>
|
||||
struct evaluator<CwiseNullaryOp<NullaryOp, PlainObjectType>> {
|
||||
typedef CwiseNullaryOp<NullaryOp, PlainObjectType> XprType;
|
||||
evaluator(XprType n) : m_functor(n.functor()) {}
|
||||
template <typename IndexType>
|
||||
typename XprType::CoeffReturnType coeff(IndexType row, IndexType col) {
|
||||
return m_wrapper(m_functor, row, col);
|
||||
}
|
||||
NullaryOp m_functor;
|
||||
nullary_wrapper m_wrapper;
|
||||
};
|
||||
template <typename BinaryOp, typename Lhs, typename Rhs>
|
||||
struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>>
|
||||
: binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> {
|
||||
evaluator(CwiseBinaryOp<BinaryOp, Lhs, Rhs> xpr)
|
||||
: binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>>(xpr) {}
|
||||
};
|
||||
template <typename BinaryOp, typename Lhs, typename Rhs>
|
||||
struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> {
|
||||
typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
|
||||
binary_evaluator(XprType xpr) : m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {}
|
||||
typename XprType::CoeffReturnType coeff(long row, long col) {
|
||||
return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col));
|
||||
}
|
||||
BinaryOp m_functor;
|
||||
evaluator<Lhs> m_lhsImpl;
|
||||
evaluator<Rhs> m_rhsImpl;
|
||||
};
|
||||
template <typename Kernel, int Index, int Stop>
|
||||
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling {
|
||||
enum { outer, inner = Index };
|
||||
static void run(Kernel kernel) {
|
||||
kernel.assignCoeffByOuterInner(outer, inner);
|
||||
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Index + 1,
|
||||
Stop>::run(kernel);
|
||||
}
|
||||
};
|
||||
template <typename Kernel, int Stop>
|
||||
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Stop,
|
||||
Stop> {
|
||||
static void run(Kernel) {}
|
||||
};
|
||||
template <typename Kernel>
|
||||
struct dense_assignment_loop {
|
||||
static void run(Kernel kernel) {
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
enum { size = DstXprType::SizeAtCompileTime, alignedSize = 0 };
|
||||
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, alignedSize,
|
||||
size>::run(kernel);
|
||||
}
|
||||
};
|
||||
template <typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT,
|
||||
typename Functor>
|
||||
class generic_dense_assignment_kernel {
|
||||
typedef typename DstEvaluatorTypeT::XprType DstXprType;
|
||||
|
||||
public:
|
||||
typedef DstEvaluatorTypeT DstEvaluatorType;
|
||||
typedef SrcEvaluatorTypeT SrcEvaluatorType;
|
||||
generic_dense_assignment_kernel(DstEvaluatorType dst, SrcEvaluatorType src,
|
||||
Functor, DstXprType& dstExpr)
|
||||
: m_dst(dst), m_src(src), m_dstExpr(dstExpr) {}
|
||||
long assignCoeff_col;
|
||||
void assignCoeffByOuterInner(long, long inner) {
|
||||
long __trans_tmp_1 = inner;
|
||||
m_functor.assignCoeff(m_dst.coeffRef(__trans_tmp_1, assignCoeff_col),
|
||||
m_src.coeff(__trans_tmp_1, assignCoeff_col));
|
||||
}
|
||||
DstEvaluatorType m_dst;
|
||||
SrcEvaluatorType m_src;
|
||||
Functor m_functor;
|
||||
DstXprType& m_dstExpr;
|
||||
};
|
||||
template <typename DstXprType, typename SrcXprType, typename Functor>
|
||||
void call_dense_assignment_loop(DstXprType& dst, SrcXprType src, Functor func) {
|
||||
typedef evaluator<DstXprType> DstEvaluatorType;
|
||||
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
||||
SrcEvaluatorType srcEvaluator(src);
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorType, SrcEvaluatorType,
|
||||
Functor>
|
||||
Kernel;
|
||||
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
||||
dense_assignment_loop<Kernel>::run(kernel);
|
||||
}
|
||||
template <typename Dst, typename Src, typename Func>
|
||||
void call_assignment_no_alias(Dst& dst, Src src, Func func) {
|
||||
enum { NeedToTranspose };
|
||||
typename conditional<NeedToTranspose, Dst&>::type actualDst(dst);
|
||||
CwiseBinaryOp<scalar_product_op, const Matrix<float, 3, 1>,
|
||||
const CwiseNullaryOp<scalar_constant_op<float>,
|
||||
const Matrix<float, 3, 1, 0, 2, 3>>>
|
||||
__trans_tmp_4 = src;
|
||||
call_dense_assignment_loop(actualDst, __trans_tmp_4, func);
|
||||
}
|
||||
template <int Size>
|
||||
struct plain_array {
|
||||
float array[Size];
|
||||
};
|
||||
template <int Size, int _Rows>
|
||||
class DenseStorage {
|
||||
plain_array<Size> m_data;
|
||||
|
||||
public:
|
||||
DenseStorage() {}
|
||||
DenseStorage(const DenseStorage&);
|
||||
static long rows() { return _Rows; }
|
||||
const float* data() const { return m_data.array; }
|
||||
float* data() { return m_data.array; }
|
||||
};
|
||||
template <typename Derived>
|
||||
class PlainObjectBase : public dense_xpr_base<Derived>::type {
|
||||
public:
|
||||
typedef typename dense_xpr_base<Derived>::type Base;
|
||||
typedef typename traits<Derived>::Scalar Scalar;
|
||||
DenseStorage<Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime> m_storage;
|
||||
long rows() const { return m_storage.rows(); }
|
||||
const Scalar* data() const { return m_storage.data(); }
|
||||
PlainObjectBase() {}
|
||||
template <typename OtherDerived>
|
||||
PlainObjectBase(const DenseBase<OtherDerived>& other) {
|
||||
_set_noalias(other);
|
||||
}
|
||||
template <typename OtherDerived>
|
||||
void _set_noalias(const DenseBase<OtherDerived>& other) {
|
||||
call_assignment_no_alias(this->derived(), other.derived(), assign_op());
|
||||
}
|
||||
};
|
||||
template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
|
||||
int _MaxCols>
|
||||
struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> {
|
||||
typedef _Scalar Scalar;
|
||||
typedef int XprKind;
|
||||
enum {
|
||||
RowsAtCompileTime = _Rows,
|
||||
ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime,
|
||||
};
|
||||
};
|
||||
template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
|
||||
int _MaxCols>
|
||||
class Matrix
|
||||
: public PlainObjectBase<
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> {
|
||||
public:
|
||||
typedef PlainObjectBase<Matrix> Base;
|
||||
typedef typename traits<Matrix>::Scalar Scalar;
|
||||
Matrix(Scalar& x, Scalar& y, Scalar& z) {
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
m_storage.data()[2] = z;
|
||||
}
|
||||
template <typename OtherDerived>
|
||||
Matrix(const EigenBase<OtherDerived>& other) : Base(other.derived()) {}
|
||||
using Base::m_storage;
|
||||
};
|
||||
template <typename BinaryOp, typename Lhs, typename Rhs>
|
||||
struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> {
|
||||
typedef typename traits<Lhs>::XprKind XprKind;
|
||||
enum { RowsAtCompileTime };
|
||||
typedef float Scalar;
|
||||
};
|
||||
template <typename>
|
||||
class CwiseBinaryOpImpl;
|
||||
template <typename, typename, typename RhsType>
|
||||
class CwiseBinaryOp : public CwiseBinaryOpImpl<RhsType> {
|
||||
public:
|
||||
typedef ref_selector::type LhsNested;
|
||||
typedef RhsType RhsNested;
|
||||
CwiseBinaryOp(const Matrix<float, 3, 1>& aLhs, RhsType& aRhs)
|
||||
: m_lhs(aLhs), m_rhs(aRhs) {}
|
||||
remove_reference<LhsNested>::type& lhs() { return m_lhs; }
|
||||
typename remove_reference<RhsNested>::type& rhs() { return m_rhs; }
|
||||
LhsNested m_lhs;
|
||||
RhsNested m_rhs;
|
||||
};
|
||||
template <typename>
|
||||
class CwiseBinaryOpImpl
|
||||
: public generic_xpr_base<CwiseBinaryOp<
|
||||
scalar_product_op, const Matrix<float, 3, 1>,
|
||||
const CwiseNullaryOp<scalar_constant_op<float>,
|
||||
const Matrix<float, 3, 1, 0, 2, 3>>>>::type {};
|
||||
template <typename NullaryOp, typename PlainObjectType>
|
||||
struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType>>
|
||||
: traits<PlainObjectType> {};
|
||||
template <typename, typename PlainObjectType>
|
||||
class CwiseNullaryOp
|
||||
: public dense_xpr_base<CwiseNullaryOp<int, PlainObjectType>>::type {
|
||||
public:
|
||||
CwiseNullaryOp(long rows, long, scalar_constant_op<float> func)
|
||||
: m_functor(func) {
|
||||
rows ? void() : __assert_fail("", "", 1, __PRETTY_FUNCTION__);
|
||||
}
|
||||
scalar_constant_op<float> functor() { return m_functor; }
|
||||
scalar_constant_op<float> m_functor;
|
||||
};
|
||||
} // namespace Eigen
|
||||
Eigen::Matrix<float, 3, 1> should_inline(float x, float y, float z,
|
||||
float scale) {
|
||||
return Eigen::Matrix<float, 3, 1>(x, y, z) * scale;
|
||||
}
|
||||
|
||||
// We should inline everything to should_inline
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Function" "optimized" } } */
|
Loading…
Add table
Reference in a new issue