Skip to content

Commit b12d891

Browse files
committed
unrolled loop optimization
1 parent 0e646f3 commit b12d891

File tree

3 files changed

+495
-20
lines changed

3 files changed

+495
-20
lines changed

include/ctll/list.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ template <typename Front, typename List> struct list_pop_pair {
3939
constexpr list_pop_pair() = default;
4040
};
4141

42+
template <typename A, typename B, typename C> struct list_pop_triple {
43+
A front{};
44+
B tail{};
45+
C other{};
46+
constexpr list_pop_triple() = default;
47+
};
48+
4249
template <typename Head, typename... As, typename T = _nothing> constexpr auto pop_and_get_front(list<Head, As...>, T = T()) noexcept -> list_pop_pair<Head, list<As...>> { return {}; }
4350
template <typename T = _nothing> constexpr auto pop_and_get_front(empty_list, T = T()) noexcept -> list_pop_pair<T, empty_list> { return {}; }
4451

include/ctre/evaluation.hpp

+62-20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "return_type.hpp"
1010
#include "find_captures.hpp"
1111
#include "first.hpp"
12+
#include "regex_count.hpp"
1213
#include <iterator>
1314

1415
// remove me when MSVC fix the constexpr bug
@@ -286,6 +287,37 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
286287
return evaluate(begin, current, end, f, captures, ctll::list<Tail...>());
287288
}
288289

290+
//check if unrollable
291+
template<typename Iterator, typename R, typename... Content, typename... Tail>
292+
constexpr auto may_unroll(ctll::list<sequence<Content...>, Tail...>, R) {
293+
return may_unroll<Iterator>(ctll::list<Content..., Tail...>{}, R{});
294+
}
295+
296+
template<typename Iterator, typename R, typename A, typename... Content, typename... Tail>
297+
constexpr auto may_unroll(ctll::list<select<A, Content...>, Tail...>, R) {
298+
constexpr auto length = ctre::pattern_length<Iterator>(sequence<select<Content...>, Tail...>{}, R{});
299+
if constexpr (atomic_pattern_length(length) && !collides(calculate_first(sequence<A,Tail...>{}), calculate_first(sequence<select<Content...>, Tail...>{}))) {
300+
if constexpr (sizeof...(Content) == 1) {
301+
if constexpr (sizeof...(Tail))
302+
return ctll::list_pop_triple<star<sequence<A,Tail...>>, sequence<Content..., Tail...>, ::std::true_type>{};
303+
else
304+
return ctll::list_pop_triple<star<A>, sequence<Content...>, ::std::true_type>{};
305+
} else {
306+
if constexpr (sizeof...(Tail))
307+
return ctll::list_pop_triple<star<sequence<A,Tail...>>, sequence<select<Content...>, Tail...>, ::std::true_type>{};
308+
else
309+
return ctll::list_pop_triple<star<A>, select<Content...>, ::std::true_type>{};
310+
}
311+
} else {
312+
return ctll::list_pop_triple<ctll::_nothing, ctll::_nothing, ::std::false_type>{};
313+
}
314+
}
315+
316+
template<typename Iterator, typename R, typename T>
317+
constexpr auto may_unroll(T, R) {
318+
return ctll::list_pop_triple<ctll::_nothing, ctll::_nothing, ::std::false_type>{};
319+
}
320+
289321
// lazy repeat
290322
template <typename R, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
291323
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, [[maybe_unused]] const flags & f, R captures, ctll::list<lazy_repeat<A,B,Content...>, Tail...>) noexcept {
@@ -409,30 +441,40 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
409441
}
410442

411443
#ifndef CTRE_DISABLE_GREEDY_OPT
412-
if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) {
444+
using unroll_t = decltype(may_unroll<Iterator>(ctll::list<Content...>{}, R{}));
445+
if constexpr (B == 0 && unroll_t{}.other) {
446+
if constexpr (A > 0) {
447+
return evaluate(begin, current, end, f, captures, ctll::list<repeat<A,A,Content...>,star<decltype(unroll_t{}.front)>, star<decltype(unroll_t{}.tail), star<decltype(unroll_t{}.front)>>, Tail...>{});
448+
} else {
449+
return evaluate(begin, current, end, f, captures, ctll::list<star<decltype(unroll_t{}.front)>, star<decltype(unroll_t{}.tail), star<decltype(unroll_t{}.front)>>, Tail...>{});
450+
}
451+
} else if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) {
413452
return evaluate(begin, current, end, f, captures, ctll::list<possessive_repeat<A,B,Content...>, Tail...>());
414-
}
453+
} else {
415454
#endif
416-
417-
// A..B
418-
size_t i{0};
419-
while (less_than<A>(i)) {
420-
auto inner_result = evaluate(begin, current, end, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
421-
422-
if (!inner_result) return not_matched;
423-
424-
captures = inner_result.unmatch();
425-
current = inner_result.get_end_position();
426-
427-
++i;
428-
}
429-
455+
456+
// A..B
457+
size_t i{ 0 };
458+
while (less_than<A>(i)) {
459+
auto inner_result = evaluate(begin, current, end, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
460+
461+
if (!inner_result) return not_matched;
462+
463+
captures = inner_result.unmatch();
464+
current = inner_result.get_end_position();
465+
466+
++i;
467+
}
468+
430469
#ifdef CTRE_MSVC_GREEDY_WORKAROUND
431-
R result;
432-
evaluate_recursive(result, i, begin, current, end, f, captures, stack);
433-
return result;
470+
R result;
471+
evaluate_recursive(result, i, begin, current, end, f, captures, stack);
472+
return result;
434473
#else
435-
return evaluate_recursive(i, begin, current, end, f, captures, stack);
474+
return evaluate_recursive(i, begin, current, end, f, captures, stack);
475+
#endif
476+
#ifndef CTRE_DISABLE_GREEDY_OPT
477+
}
436478
#endif
437479

438480
}

0 commit comments

Comments
 (0)