Skip to content

Commit 6db2002

Browse files
committed
unrolled loop optimization
1 parent 0e646f3 commit 6db2002

File tree

4 files changed

+579
-32
lines changed

4 files changed

+579
-32
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 "pattern_length.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
}

include/ctre/first.hpp

+18-12
Original file line numberDiff line numberDiff line change
@@ -382,18 +382,6 @@ template <size_t Capacity> class point_set {
382382
};
383383
point points[Capacity+1]{};
384384
size_t used{0};
385-
constexpr point * begin() {
386-
return points;
387-
}
388-
constexpr point * begin() const {
389-
return points;
390-
}
391-
constexpr point * end() {
392-
return points + used;
393-
}
394-
constexpr point * end() const {
395-
return points + used;
396-
}
397385
constexpr point * lower_bound(point obj) {
398386
auto first = begin();
399387
auto last = end();
@@ -444,6 +432,24 @@ template <size_t Capacity> class point_set {
444432
insert_point(low, high);
445433
//insert_point(high, low);
446434
}
435+
constexpr point* begin() {
436+
return points;
437+
}
438+
constexpr point* begin() const {
439+
return points;
440+
}
441+
constexpr point* end() {
442+
return points + used;
443+
}
444+
constexpr point* end() const {
445+
return points + used;
446+
}
447+
constexpr size_t size() {
448+
return used;
449+
}
450+
constexpr size_t size() const {
451+
return used;
452+
}
447453
constexpr bool check(int64_t low, int64_t high) {
448454
for (auto r: *this) {
449455
if (r.low <= low && low <= r.high) {

0 commit comments

Comments
 (0)