1#ifndef __DUNE_ACFEM_EXPRESSIONS_CSEOPTIMIZATION_HH__
2#define __DUNE_ACFEM_EXPRESSIONS_CSEOPTIMIZATION_HH__
4#include "../common/ostream.hh"
5#include "../mpl/subtuple.hh"
6#include "../mpl/compare.hh"
7#include "../mpl/typetupleutil.hh"
8#include "examineutil.hh"
10#include "treeextract.hh"
11#include "optimizationbase.hh"
12#include "runtimeequal.hh"
13#include "subexpression.hh"
19 namespace Expressions {
21 using ACFem::operator==;
25 template<
class Expr,
template<
class...>
class IsCandidate, std::ptrdiff_t N = -1>
26 struct IsSubExpressionCandidate
29 template<
class T,
class Parent,
class SFINAE =
void>
31 : IsCandidate<T, Parent, Expr>
35 template<
class T,
class Parent>
36 struct Predicate<T, Parent,
37 std::enable_if_t<std::is_same<Parent, void>::value || (N != -1 && Depth<T>::value != (std::size_t)N)> >
42 using Ignore = BoolConstant<IsSelfExpression<T>::value || (Depth<T>::value < N)>;
46 template<
class T,
class SExp,
class SFINAE =
void>
54 template<
class T,
class SExp>
58 std::enable_if_t<(IsSubExpressionExpression<T>::value
59 && AreRuntimeEqual<Operand<1, T>, Operand<1, SExp> >::value
67 template<
class Traits,
class DepthTuple>
71 template<
class T,
class SFINAE =
void>
83 template<
class Traits,
class DepthTuple>
110 template<
template<
class...>
class P>
111 struct OrMatchTreePos
113 template<
class T1,
class T2,
class SFINAE =
void>
116 template<
class E,
class TreePos,
class SExp>
118 MPL::TypeTuple<E, TreePos>, SExp, std::enable_if_t<IsSubExpressionExpression<SExp>::value> >
119 :
BoolConstant<(P<E, SExp>::value || std::is_same<TreePos, typename SubExpressionTraits<SExp>::TreePos>::value)>
124 template<
template<
class...>
class MatchPredicate,
class SExp,
class TreePos,
class PrevDepth>
125 constexpr decltype(
auto) injectSubExpressionsOneLevel(
126 SExp&& sExp, TreePos, PrevDepth&& prevDepth, IndexSequence<>)
128 return forwardReturnValue<SExp>(sExp);
132 template<
template<
class...>
class MatchPredicate,
class SExp,
class TreePos,
class Traits,
class PrevDepth, std::size_t I0, std::size_t... ArgIdx>
133 constexpr auto injectSubExpressionsOneLevel(
136 const CommonSubExpressionCascade<Traits, PrevDepth>& prevDepth,
137 IndexSequence<I0, ArgIdx...>)
139 return injectSubExpressionsOneLevel<MatchPredicate>(
140 replaceMatching<OrMatchTreePos<MatchPredicate>::template Predicate, IsSubExpressionExpression>(
141 std::forward<SExp>(sExp), std::get<I0>(prevDepth.get()),
DontOptimize{}, TreePos{}),
144 IndexSequence<ArgIdx...>{});
148 template<
template<
class...>
class MatchPredicate,
class SExp,
class Traits,
class TreePos, std::enable_if_t<IsExpression<SExp>::value,
int> = 0>
149 constexpr decltype(
auto) injectSubExpressionsRecursion(
152 const CommonSubExpressionCascade<Traits, std::tuple<std::tuple<> > >& prevDepth)
154 return forwardReturnValue<SExp>(sExp);
158 template<
template<
class...>
class MatchPredicate,
class SExp,
class TreePos,
class Traits,
class PrevDepth,
class... PrevDepthRest,
159 std::enable_if_t<(IsExpression<SExp>::value &&
sizeof...(PrevDepthRest) > 0),
int> = 0>
160 constexpr decltype(
auto) injectSubExpressionsRecursion(
163 const CommonSubExpressionCascade<Traits, std::tuple<PrevDepth, PrevDepthRest...> >& prevDepth)
165 using PrevProvider = CommonSubExpressionCascade<Traits, std::tuple<PrevDepthRest...> >;
168 auto thisLevel = injectSubExpressionsOneLevel<MatchPredicate>(std::forward<SExp>(sExp),
171 MakeSequenceFor<PrevDepth>{});
173 return injectSubExpressionsRecursion<MatchPredicate>(
asExpression(std::move(thisLevel)), TreePos{},
static_cast<const PrevProvider&
>(prevDepth));
178 template<
class Tuple,
class Traits,
class PrevDepth, std::size_t... Idx>
179 constexpr auto injectSubExpressionsExpander(
181 const CommonSubExpressionCascade<Traits, PrevDepth>& prevDepth,
182 IndexSequence<Idx...>)
184 return std::make_tuple(
186 subExpression<Traits::template Storage>(
187 injectSubExpressionsRecursion<AreRuntimeEqual>(
188 std::move(std::get<Idx>(std::forward<Tuple>(tuple)).first),
189 std::get<Idx>(std::forward<Tuple>(tuple)).second,
192 std::get<Idx>(std::forward<Tuple>(tuple)).second
200 template<
class Tuple,
class Traits,
class PrevDepth, std::size_t... Idx>
201 constexpr auto replaceSubExpressionsExpander(
203 const CommonSubExpressionCascade<Traits, PrevDepth>& prevDepth,
204 IndexSequence<Idx...>)
206 return std::make_tuple(
208 subExpression<Traits::template Storage>(
209 injectSubExpressionsRecursion<IsMatchingSubExpression>(
210 std::move(std::get<Idx>(std::forward<Tuple>(tuple)).operand(1_c)),
211 typename SubExpressionTraits<TupleElement<Idx, Tuple> >::TreePos{},
214 typename SubExpressionTraits<TupleElement<Idx, Tuple> >::TreePos{}
232 template<
class T,
class... SExpNode,
class Traits,
class PrevDepth>
233 constexpr auto injectSubExpressions(T&& t, MPL::TypeTuple<SExpNode...>,
const CommonSubExpressionCascade<Traits, PrevDepth>& prevDepth)
235 return std::make_tuple(
237 subExpression<Traits::template Storage>(
238 injectSubExpressionsRecursion<AreRuntimeEqual>(
239 std::move(treeOperand(std::forward<T>(t),
typename SExpNode::Second{})),
240 typename SExpNode::Second{},
243 typename SExpNode::Second{}
262 template<
class Expr,
class Traits,
class Cascade,
class TreePos = IndexSequence<>,
263 std::enable_if_t<!IsTupleLike<Expr>::value,
int> = 0>
264 constexpr auto injectSubExpressions(Expr&& expr,
const CommonSubExpressionCascade<Traits, Cascade>& cascade, TreePos = TreePos{})
285 template<class T, class Traits, class PrevDepth, std::enable_if_t<IsTupleLike<T>::value,
int> = 0>
286 constexpr auto replaceSubExpressions(T&& tuple,
287 const CommonSubExpressionCascade<Traits, PrevDepth>& prevDepth)
289 return replaceSubExpressionsExpander(std::forward<T>(tuple), prevDepth, MakeSequenceFor<T>{});
307 template<
class Expr,
class Traits,
class Cascade,
class TreePos = IndexSequence<>,
308 std::enable_if_t<!IsTupleLike<Expr>::value,
int> = 0>
309 constexpr auto replaceSubExpressions(Expr&& expr,
const CommonSubExpressionCascade<Traits, Cascade>& cascade, TreePos = TreePos{})
322 template<
class Traits>
325 static constexpr std::size_t depth_ = 0;
327 using DepthType = std::tuple<>;
328 using DepthTupleType = std::tuple<DepthType>;
329 using TraitsType = Traits;
332 : traits_(std::forward<Traits>(t))
336 : traits_(std::forward<Traits>(t))
339 template<std::
size_t D = 0>
342 static_assert(D == 0,
"This is the terminal cascade element, D should be 0.");
346 template<std::
size_t D = 0>
349 static_assert(D == 0,
"This is the terminal cascade element, D should be 0.");
353 template<std::
size_t D = 0>
356 static_assert(D == 0,
"This is the terminal cascade element, D should be 0.");
363 constexpr static std::size_t depth()
368 static constexpr bool isEmpty()
373 const TraitsType& sExpTraits()
const
384 template<
class Traits,
class... SExp,
class PrevSExp,
class... SExpRest>
393 "Only allowed for proper sub-expressions.");
395 using DepthType = std::tuple<SExp...>;
396 using DepthTupleType = std::tuple<std::tuple<SExp...>, PrevSExp, SExpRest...>;
397 using typename BaseType::TraitsType;
398 using BaseType::sExpTraits;
400 static_assert(std::is_same<typename BaseType::DepthType, PrevSExp>::value,
401 "Bug, inconsistent data types.");
403 static constexpr std::size_t depth_ =
sizeof...(SExpRest) + 2;
405 template<
class T,
class... SExpNode>
408 , data_(injectSubExpressions(std::forward<T>(t), sExpTuple,
static_cast<const BaseType&
>(*
this)))
410 static_assert(
sizeof...(SExpNode) ==
sizeof...(SExp),
"Mismatching numbers of expressions.");
415 , data_(replaceSubExpressions(
const_cast<DepthType&
>(other.data_),
static_cast<const BaseType&
>(*
this)))
420 , data_(replaceSubExpressions(std::move(other.data_),
static_cast<const BaseType&
>(*
this)))
423 template<std::
size_t D = 0, std::enable_if_t<(D == 0),
int> = 0>
429 template<std::
size_t D = 0, std::enable_if_t<(D == 0),
int> = 0>
435 template<std::
size_t D = 0, std::enable_if_t<(D == 0),
int> = 0>
441 template<std::
size_t D, std::enable_if_t<(D > 0),
int> = 0>
444 return BaseType::template
get<D-1>();
447 template<std::
size_t D, std::enable_if_t<(D > 0),
int> = 0>
450 return BaseType::template
get<D-1>();
453 template<std::
size_t D, std::enable_if_t<(D > 0),
int> = 0>
456 return BaseType::template
get<D-1>();
460 template<
class SExpTraits = TraitsType>
464 forEach(data_, [&traits](
auto&& sExp) {
476 return static_cast<BaseType&&
>(*this);
481 return static_cast<BaseType&
>(*this);
484 const auto& base() const&
486 return static_cast<const BaseType&
>(*this);
489 constexpr static std::size_t depth()
494 static constexpr bool isEmpty()
496 return size<DepthType>() == 0 && BaseType::isEmpt();
503 template<
class A,
class B>
504 using Unique = Expressions::AreRuntimeEqual<typename A::First, typename B::First>;
506 template<
class E,
class TreePos,
class... T>
507 using ProcessUnique = MPL::JoinUnless<Unique, T...>;
509 template<
class T,
class Traits, std::
size_t D>
510 struct CascadeBuildTraits;
512 template<
class T,
class Traits>
513 struct CascadeBuildTraits<T, Traits, 0>
515 using ExprType = EnclosedType<T>;
516 using DepthType = MPL::TypeTuple<>;
517 using SExpTuple = std::tuple<>;
518 using DepthTuple = std::tuple<std::tuple<> >;
519 using CascadeType = CommonSubExpressionCascade<Traits, DepthTuple>;
522 template<
class T,
class Traits, std::
size_t N>
523 struct CascadeBuildTraits
525 using IsCandidate = IsSubExpressionCandidate<T, Traits::template IsCandidate, N>;
526 using ExprType = EnclosedType<T>;
527 using DepthType = Expressions::TreeExtract<
528 IsCandidate::template Predicate,
529 ExprType, Expressions::PackTreePair, Expressions::TreePosition<>,
530 IsCandidate::template Ignore, ProcessUnique>;
531 using PrevTraits = CascadeBuildTraits<T, Traits, N-1>;
532 using PrevCascade =
typename PrevTraits::CascadeType;
534 std::decay_t<decltype(injectSubExpressions(std::declval<T>(), DepthType{}, std::declval<const PrevCascade&>()))>;
535 static constexpr bool empty = size<SExpTuple>() == 0;
536 using DepthTuple = ConditionalType<empty,
537 typename PrevTraits::DepthTuple,
538 AddFrontTuple<SExpTuple, typename PrevTraits::DepthTuple> >;
539 using CascadeType = CommonSubExpressionCascade<Traits, DepthTuple>;
542 template<class T, class Traits, std::size_t N = Depth<T>::value,
543 std::enable_if_t<(IsExpression<T>::value
544 && !IsClosure<T>::value
547 auto commonSubExpressionCascade(T&& t, Traits&& traits, IndexConstant<N> = IndexConstant<N>{})
550 using BuildTraits = CascadeBuildTraits<T, Traits, N>;
551 using CascadeType =
typename BuildTraits::CascadeType;
552 return CascadeType(std::tuple<>{}, std::forward<Traits>(traits));
566 template<class T, class Traits, std::size_t N = Depth<T>::value,
567 std::enable_if_t<(IsExpression<T>::value
568 && !IsClosure<T>::value
571 auto commonSubExpressionCascade(T&& t, Traits&& traits, IndexConstant<N> = IndexConstant<N>{})
574 using BuildTraits = CascadeBuildTraits<T, Traits, N>;
575 if constexpr (BuildTraits::empty) {
576 return Expressions::commonSubExpressionCascade(std::forward<T>(t), std::forward<Traits>(traits), IndexConstant<N-1>{});
578 using IsCandidate =
typename BuildTraits::IsCandidate;
579 using SExpTuple = Expressions::TreeExtract<
580 IsCandidate::template Predicate,
581 T, Expressions::PackTreePair, Expressions::TreePosition<>,
582 IsCandidate::template Ignore, ProcessUnique>;
584 using CascadeType =
typename BuildTraits::CascadeType;
586 Expressions::commonSubExpressionCascade(std::forward<T>(t), std::forward<Traits>(traits), IndexConstant<N-1>{}),
587 std::forward<T>(t), SExpTuple{}
592 template<
class T,
class Traits,
593 std::enable_if_t<(IsExpression<T>::value
594 && IsClosure<T>::value
596 auto commonSubExpressionCascade(T&& t, Traits&& traits)
598 return Expressions::commonSubExpressionCascade(
asExpression(std::forward<T>(t)), std::forward<Traits>(traits));
603 template<
template<
class T,
class...>
class F,
608 template<
class...>
class Unique,
609 std::enable_if_t<(N >= size<Input>()),
int> = 0>
610 auto extractFromCSEHelper(Input&& input,
612 Recursive r, PredicateWrapper<Unique> u)
614 return std::forward<Initial>(initial);
617 template<
template<
class T,
class...>
class F,
622 template<
class...>
class Unique,
623 std::enable_if_t<(N < size<Input>()),
int> = 0>
624 auto extractFromCSEHelper(Input&& input,
626 Recursive r, PredicateWrapper<Unique> u)
628 return extractFromCSEHelper<F, N+1>(
629 std::forward<Input>(input),
632 get<N>(std::forward<Input>(input)),
633 std::forward<Initial>(initial),
650 template<
template<
class T,
class...>
class F,
652 class Initial = std::tuple<>,
655 std::enable_if_t<IsCSECascade<T>::value && std::decay_t<T>::depth() != 0,
int> = 0>
656 auto extract(T&& cascade,
657 Initial&& initial = Initial{},
658 Recursive r = Recursive{},
659 PredicateWrapper<Unique> u = PredicateWrapper<Unique>{})
661 return extract<F>(std::forward<T>(cascade).base(),
662 extractFromCSEHelper<F, 0>(
663 std::forward<T>(cascade).
get(),
664 std::forward<Initial>(initial),
671 template<
template<
class T,
class...>
class F,
673 class Initial = std::tuple<>,
676 std::enable_if_t<IsCSECascade<T>::value && std::decay_t<T>::depth() == 0,
int> = 0>
677 auto extract(T&& cascade,
678 Initial&& initial = Initial{},
679 Recursive r = Recursive{},
680 PredicateWrapper<Unique> u = PredicateWrapper<Unique>{})
682 return std::forward<Initial>(initial);
void evaluate(SExpTraits &&traits)
Evalute all contained sub-expressions, lowest level first.
Definition: cseoptimization.hh:461
Wrap tuple of subexpressions with constant references to sub-expressions of lower levels.
Definition: cseoptimization.hh:68
constexpr decltype(auto) asExpression(T &&t)
Return a non-closure expression as is.
Definition: interface.hh:122
constexpr decltype(auto) expressionClosure(T &&t)
Do-nothing default implementation for pathologic cases.
Definition: interface.hh:93
OptimizeTag< 0 > DontOptimize
Bottom level is overloaded to do nothing.
Definition: optimizationbase.hh:74
constexpr decltype(auto) evaluate(Optimize, T &&t)
Evaluate an expression or expression Expressions::Storage container.
Definition: optimizationbase.hh:206
constexpr decltype(auto) get(T &&t, IndexConstant< I >=IndexConstant< I >{})
Access to the i-the element.
Definition: access.hh:129
void evaluateSubExpression(T &&t, Functor &&f=Functor{})
Copy the value of the contained sub-expression (operand no.
Definition: subexpression.hh:125
Sequence< std::size_t, V... > IndexSequence
Sequence of std::size_t values.
Definition: types.hh:64
Constant< bool, V > BoolConstant
Short-cut for integral constant of type bool.
Definition: types.hh:48
Constant< std::size_t, V > IndexConstant
Short-cut for integral constant of type std::size_t.
Definition: types.hh:44
typename MakeType< FalseType, Other... >::Type AlwaysFalse
Generate FalseType regardless of the template argument list.
Definition: types.hh:155
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
Definition: cseoptimization.hh:74
Definition: cseoptimization.hh:49