lookaround: reduce compile time for trimLiterals

This commit is contained in:
Justin Viiret 2017-02-01 14:47:05 +11:00 committed by Matthew Barr
parent 8ee8f5f236
commit c4bfe0449c

View File

@ -460,13 +460,24 @@ void findFloodReach(const RoseBuildImpl &tbi, const RoseVertex v,
} }
} }
static
map<s32, CharReach> findLiteralReach(const rose_literal_id &lit) {
map<s32, CharReach> look;
u32 i = lit.delay + 1; namespace {
for (auto it = lit.s.rbegin(), ite = lit.s.rend(); it != ite; ++it) { struct LookProto {
look[0 - i] |= *it; LookProto(s32 offset_in, CharReach reach_in)
: offset(offset_in), reach(move(reach_in)) {}
s32 offset;
CharReach reach;
};
}
static
vector<LookProto> findLiteralReach(const rose_literal_id &lit) {
vector<LookProto> look;
look.reserve(lit.s.length());
s32 i = 0 - lit.s.length() - lit.delay;
for (const auto &c : lit.s) {
look.emplace_back(i, c);
i++; i++;
} }
@ -478,22 +489,40 @@ map<s32, CharReach> findLiteralReach(const RoseBuildImpl &build,
const RoseVertex v) { const RoseVertex v) {
bool first = true; bool first = true;
map<s32, CharReach> look; map<s32, CharReach> look;
for (u32 lit_id : build.g[v].literals) { for (u32 lit_id : build.g[v].literals) {
const rose_literal_id &lit = build.literals.right.at(lit_id); const rose_literal_id &lit = build.literals.right.at(lit_id);
auto lit_look = findLiteralReach(lit); auto lit_look = findLiteralReach(lit);
if (first) { if (first) {
look = move(lit_look); for (auto &p : lit_look) {
look.emplace(p.offset, p.reach);
}
first = false; first = false;
} else { continue;
for (auto it = look.begin(); it != look.end();) { }
auto l_it = lit_look.find(it->first);
if (l_it == lit_look.end()) { // Erase elements from look with keys not in lit_look. Where a key is
it = look.erase(it); // in both maps, union its reach with the lookaround.
} else { auto jt = begin(lit_look);
it->second |= l_it->second; for (auto it = begin(look); it != end(look);) {
++it; if (jt == end(lit_look)) {
} // No further lit_look entries, erase remaining elements from
// look.
look.erase(it, end(look));
break;
}
if (it->first < jt->offset) {
// Offset is present in look but not in lit_look, erase.
it = look.erase(it);
} else if (it->first > jt->offset) {
// Offset is preset in lit_look but not in look, ignore.
++jt;
} else {
// Offset is present in both, union its reach with look.
it->second |= jt->reach;
++it;
++jt;
} }
} }
} }