]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
rose_build_groups: move findGroupSquashers
authorJustin Viiret <justin.viiret@intel.com>
Thu, 2 Jun 2016 03:24:47 +0000 (13:24 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Fri, 8 Jul 2016 00:47:07 +0000 (10:47 +1000)
src/rose/rose_build_compile.cpp
src/rose/rose_build_groups.cpp
src/rose/rose_build_groups.h

index af8f7e960c479dd375c60f2ec8494d890823cfa0..dca7310cc0cc4ba4715f92b33848a215d21cf9a4 100644 (file)
@@ -34,6 +34,7 @@
 #include "rose_build_castle.h"
 #include "rose_build_convert.h"
 #include "rose_build_dump.h"
+#include "rose_build_groups.h"
 #include "rose_build_matchers.h"
 #include "rose_build_merge.h"
 #include "rose_build_role_aliasing.h"
@@ -843,189 +844,6 @@ bool RoseBuildImpl::hasAnchoredTablePred(RoseVertex v) const {
     return false;
 }
 
-/* returns true if every vertex associated with a groups also belongs to
-   lit_info */
-static
-bool coversGroup(const RoseBuildImpl &tbi, const rose_literal_info &lit_info) {
-    if (lit_info.vertices.empty()) {
-        DEBUG_PRINTF("no vertices - does not cover\n");
-        return false;
-    }
-
-    if (!lit_info.group_mask) {
-        DEBUG_PRINTF("no group - does not cover\n");
-        return false; /* no group (not a floating lit?) */
-    }
-
-    assert(popcount64(lit_info.group_mask) == 1);
-
-    /* for each lit in group, ensure that vertices are a subset of lit_info's */
-    rose_group groups = lit_info.group_mask;
-    while (groups) {
-        u32 group_id = findAndClearLSB_64(&groups);
-        for (u32 id : tbi.group_to_literal.at(group_id)) {
-            DEBUG_PRINTF(" checking against friend %u\n", id);
-            if (!is_subset_of(tbi.literal_info[id].vertices,
-                              lit_info.vertices)) {
-                DEBUG_PRINTF("fail\n");
-                return false;
-            }
-        }
-    }
-
-    DEBUG_PRINTF("ok\n");
-    return true;
-}
-
-static
-bool isGroupSquasher(const RoseBuildImpl &tbi, const u32 id /* literal id */,
-                     rose_group forbidden_squash_group) {
-    const RoseGraph &g = tbi.g;
-
-    const rose_literal_info &lit_info = tbi.literal_info.at(id);
-
-    DEBUG_PRINTF("checking if %u '%s' is a group squasher %016llx\n", id,
-                  dumpString(tbi.literals.right.at(id).s).c_str(),
-                  lit_info.group_mask);
-
-    if (tbi.literals.right.at(id).table == ROSE_EVENT) {
-        DEBUG_PRINTF("event literal, has no groups to squash\n");
-        return false;
-    }
-
-    if (!coversGroup(tbi, lit_info)) {
-        DEBUG_PRINTF("does not cover group\n");
-        return false;
-    }
-
-    if (lit_info.group_mask & forbidden_squash_group) {
-        /* probably a delayed lit */
-        DEBUG_PRINTF("skipping as involves a forbidden group\n");
-        return false;
-    }
-
-    // Single-vertex, less constrained case than the multiple-vertex one below.
-    if (lit_info.vertices.size() == 1) {
-        const RoseVertex &v = *lit_info.vertices.begin();
-
-        if (tbi.hasDelayPred(v)) { /* due to rebuild issues */
-            return false;
-        }
-
-        /* there are two ways to be a group squasher:
-         * 1) only care about the first accepted match
-         * 2) can only match once after a pred match
-         *
-         * (2) requires analysis of the infix before v and is not implemented,
-         * TODO
-         */
-
-        /* Case 1 */
-
-        // Can't squash cases with accepts
-        if (!g[v].reports.empty()) {
-            return false;
-        }
-
-        /* Can't squash cases with a suffix without analysis of the suffix.
-         * TODO: look at suffixes */
-        if (g[v].suffix) {
-            return false;
-        }
-
-        // Out-edges must have inf max bound, + no other shenanigans */
-        for (const auto &e : out_edges_range(v, g)) {
-            if (g[e].maxBound != ROSE_BOUND_INF) {
-                return false;
-            }
-
-            if (g[target(e, g)].left) {
-                return false; /* is an infix rose trigger, TODO: analysis */
-            }
-        }
-
-        DEBUG_PRINTF("%u is a path 1 group squasher\n", id);
-        return true;
-
-        /* note: we could also squash the groups of its preds (if nobody else is
-         * using them. TODO. */
-    }
-
-    // Multiple-vertex case
-    for (auto v : lit_info.vertices) {
-        assert(!tbi.isAnyStart(v));
-
-        // Can't squash cases with accepts
-        if (!g[v].reports.empty()) {
-            return false;
-        }
-
-        // Suffixes and leftfixes are out too as first literal may not match
-        // for everyone.
-        if (!g[v].isBoring()) {
-            return false;
-        }
-
-        /* TODO: checks are solid but we should explain */
-        if (tbi.hasDelayPred(v) || tbi.hasAnchoredTablePred(v)) {
-            return false;
-        }
-
-        // Out-edges must have inf max bound and not directly lead to another
-        // vertex with this group, e.g. 'foobar.*foobar'.
-        for (const auto &e : out_edges_range(v, g)) {
-            if (g[e].maxBound != ROSE_BOUND_INF) {
-                return false;
-            }
-            RoseVertex t = target(e, g);
-
-            if (g[t].left) {
-                return false; /* is an infix rose trigger */
-            }
-
-            for (u32 lit_id : g[t].literals) {
-                if (tbi.literal_info[lit_id].group_mask & lit_info.group_mask) {
-                    return false;
-                }
-            }
-        }
-
-        // In-edges must all be dot-stars with no overlap at all, as overlap
-        // also causes history to be used.
-        /* Different tables are already forbidden by previous checks */
-        for (const auto &e : in_edges_range(v, g)) {
-            if (!(g[e].minBound == 0 && g[e].maxBound == ROSE_BOUND_INF)) {
-                return false;
-            }
-
-            // Check overlap, if source was a literal.
-            RoseVertex u = source(e, g);
-            if (tbi.maxLiteralOverlap(u, v)) {
-                return false;
-            }
-        }
-    }
-
-    DEBUG_PRINTF("literal %u is a multi-vertex group squasher\n", id);
-    return true;
-}
-
-static
-void findGroupSquashers(RoseBuildImpl &tbi) {
-    rose_group forbidden_squash_group = 0;
-    for (const auto &e : tbi.literals.right) {
-        if (e.second.delay) {
-            forbidden_squash_group |= tbi.literal_info[e.first].group_mask;
-        }
-    }
-
-    for (u32 id = 0; id < tbi.literal_info.size(); id++) {
-        if (isGroupSquasher(tbi, id, forbidden_squash_group)) {
-            tbi.literal_info[id].squash_group = true;
-        }
-    }
-}
-
 void RoseBuildImpl::findTransientLeftfixes(void) {
     for (auto v : vertices_range(g)) {
         if (!g[v].left) {
index 4fc125d2e2a35b6aebcda20c6b05aaefb9e67694..5467e1abea26a29d33c76fcc0bc51e1f75d4a909 100644 (file)
@@ -454,4 +454,190 @@ rose_group getSquashableGroups(const RoseBuildImpl &build) {
     return squashable_groups;
 }
 
+/**
+ * \brief True if every vertex associated with a group also belongs to
+ * lit_info.
+ */
+static
+bool coversGroup(const RoseBuildImpl &build,
+                 const rose_literal_info &lit_info) {
+    if (lit_info.vertices.empty()) {
+        DEBUG_PRINTF("no vertices - does not cover\n");
+        return false;
+    }
+
+    if (!lit_info.group_mask) {
+        DEBUG_PRINTF("no group - does not cover\n");
+        return false; /* no group (not a floating lit?) */
+    }
+
+    assert(popcount64(lit_info.group_mask) == 1);
+
+    /* for each lit in group, ensure that vertices are a subset of lit_info's */
+    rose_group groups = lit_info.group_mask;
+    while (groups) {
+        u32 group_id = findAndClearLSB_64(&groups);
+        for (u32 id : build.group_to_literal.at(group_id)) {
+            DEBUG_PRINTF(" checking against friend %u\n", id);
+            if (!is_subset_of(build.literal_info[id].vertices,
+                              lit_info.vertices)) {
+                DEBUG_PRINTF("fail\n");
+                return false;
+            }
+        }
+    }
+
+    DEBUG_PRINTF("ok\n");
+    return true;
+}
+
+static
+bool isGroupSquasher(const RoseBuildImpl &build, const u32 id /* literal id */,
+                     rose_group forbidden_squash_group) {
+    const RoseGraph &g = build.g;
+
+    const rose_literal_info &lit_info = build.literal_info.at(id);
+
+    DEBUG_PRINTF("checking if %u '%s' is a group squasher %016llx\n", id,
+                  dumpString(build.literals.right.at(id).s).c_str(),
+                  lit_info.group_mask);
+
+    if (build.literals.right.at(id).table == ROSE_EVENT) {
+        DEBUG_PRINTF("event literal, has no groups to squash\n");
+        return false;
+    }
+
+    if (!coversGroup(build, lit_info)) {
+        DEBUG_PRINTF("does not cover group\n");
+        return false;
+    }
+
+    if (lit_info.group_mask & forbidden_squash_group) {
+        /* probably a delayed lit */
+        DEBUG_PRINTF("skipping as involves a forbidden group\n");
+        return false;
+    }
+
+    // Single-vertex, less constrained case than the multiple-vertex one below.
+    if (lit_info.vertices.size() == 1) {
+        const RoseVertex &v = *lit_info.vertices.begin();
+
+        if (build.hasDelayPred(v)) { /* due to rebuild issues */
+            return false;
+        }
+
+        /* there are two ways to be a group squasher:
+         * 1) only care about the first accepted match
+         * 2) can only match once after a pred match
+         *
+         * (2) requires analysis of the infix before v and is not implemented,
+         * TODO
+         */
+
+        /* Case 1 */
+
+        // Can't squash cases with accepts
+        if (!g[v].reports.empty()) {
+            return false;
+        }
+
+        /* Can't squash cases with a suffix without analysis of the suffix.
+         * TODO: look at suffixes */
+        if (g[v].suffix) {
+            return false;
+        }
+
+        // Out-edges must have inf max bound, + no other shenanigans */
+        for (const auto &e : out_edges_range(v, g)) {
+            if (g[e].maxBound != ROSE_BOUND_INF) {
+                return false;
+            }
+
+            if (g[target(e, g)].left) {
+                return false; /* is an infix rose trigger, TODO: analysis */
+            }
+        }
+
+        DEBUG_PRINTF("%u is a path 1 group squasher\n", id);
+        return true;
+
+        /* note: we could also squash the groups of its preds (if nobody else is
+         * using them. TODO. */
+    }
+
+    // Multiple-vertex case
+    for (auto v : lit_info.vertices) {
+        assert(!build.isAnyStart(v));
+
+        // Can't squash cases with accepts
+        if (!g[v].reports.empty()) {
+            return false;
+        }
+
+        // Suffixes and leftfixes are out too as first literal may not match
+        // for everyone.
+        if (!g[v].isBoring()) {
+            return false;
+        }
+
+        /* TODO: checks are solid but we should explain */
+        if (build.hasDelayPred(v) || build.hasAnchoredTablePred(v)) {
+            return false;
+        }
+
+        // Out-edges must have inf max bound and not directly lead to another
+        // vertex with this group, e.g. 'foobar.*foobar'.
+        for (const auto &e : out_edges_range(v, g)) {
+            if (g[e].maxBound != ROSE_BOUND_INF) {
+                return false;
+            }
+            RoseVertex t = target(e, g);
+
+            if (g[t].left) {
+                return false; /* is an infix rose trigger */
+            }
+
+            for (u32 lit_id : g[t].literals) {
+                if (build.literal_info[lit_id].group_mask &
+                    lit_info.group_mask) {
+                    return false;
+                }
+            }
+        }
+
+        // In-edges must all be dot-stars with no overlap at all, as overlap
+        // also causes history to be used.
+        /* Different tables are already forbidden by previous checks */
+        for (const auto &e : in_edges_range(v, g)) {
+            if (!(g[e].minBound == 0 && g[e].maxBound == ROSE_BOUND_INF)) {
+                return false;
+            }
+
+            // Check overlap, if source was a literal.
+            RoseVertex u = source(e, g);
+            if (build.maxLiteralOverlap(u, v)) {
+                return false;
+            }
+        }
+    }
+
+    DEBUG_PRINTF("literal %u is a multi-vertex group squasher\n", id);
+    return true;
+}
+
+void findGroupSquashers(RoseBuildImpl &build) {
+    rose_group forbidden_squash_group = 0;
+    for (const auto &e : build.literals.right) {
+        if (e.second.delay) {
+            forbidden_squash_group |= build.literal_info[e.first].group_mask;
+        }
+    }
+
+    for (u32 id = 0; id < build.literal_info.size(); id++) {
+        if (isGroupSquasher(build, id, forbidden_squash_group)) {
+            build.literal_info[id].squash_group = true;
+        }
+    }
+}
+
 } // namespace ue2
index 608eda4adb6c203ef70368455327a1c902fe4760..f24a11c3953c01cfa2aafe3572c3a0bc34acd323 100644 (file)
@@ -44,6 +44,8 @@ getVertexGroupMap(const RoseBuildImpl &build);
 
 rose_group getSquashableGroups(const RoseBuildImpl &build);
 
+void findGroupSquashers(RoseBuildImpl &build);
+
 } // namespace ue2
 
 #endif // ROSE_BUILD_GROUPS_H