]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
be more selective about generating CLEAR_WORK_DONE instructions
authorAlex Coyte <a.coyte@intel.com>
Tue, 11 Apr 2017 00:50:16 +0000 (10:50 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Tue, 30 May 2017 03:58:32 +0000 (13:58 +1000)
src/rose/rose_build_bytecode.cpp
src/rose/rose_build_program.cpp
src/rose/rose_build_program.h

index 620ba3df1d279ef772efe1a6a0f10eb39c5f3151..bd7481ab1310e8bc0662d5a6de77e0edaa7f5ce5 100644 (file)
@@ -4879,8 +4879,11 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
 }
 
 /**
- * \brief Consumes list of program blocks, checks them for duplicates and then
- * concatenates them into one program.
+ * \brief Consumes list of program blocks corresponding to different literals,
+ * checks them for duplicates and then concatenates them into one program.
+ *
+ * Note: if a block will squash groups, a CLEAR_WORK_DONE instruction is
+ * inserted to prevent the work_done flag being contaminated by early blocks.
  */
 static
 RoseProgram assembleProgramBlocks(vector<RoseProgram> &&blocks) {
@@ -4899,8 +4902,18 @@ RoseProgram assembleProgramBlocks(vector<RoseProgram> &&blocks) {
 
     DEBUG_PRINTF("%zu blocks after dedupe\n", blocks.size());
 
-    for (auto &prog : blocks) {
-        program.add_block(move(prog));
+    for (auto &block : blocks) {
+        /* If we have multiple blocks from different literals and any of them
+         * squash groups, we will have to add a CLEAR_WORK_DONE instruction to
+         * each literal program block to clear the work_done flags so that it's
+         * only set if a state has been. */
+        if (!program.empty() && reads_work_done_flag(block)) {
+            RoseProgram clear_block;
+            clear_block.add_before_end(make_unique<RoseInstrClearWorkDone>());
+            program.add_block(move(clear_block));
+        }
+
+        program.add_block(move(block));
     }
 
     return program;
@@ -4913,28 +4926,10 @@ RoseProgram makeFragmentProgram(const RoseBuildImpl &build, build_context &bc,
                                const map<u32, vector<RoseEdge>> &lit_edge_map) {
     assert(!lit_ids.empty());
 
-    // If we have multiple literals and any of them squash groups, we will have
-    // to add a CLEAR_WORK_DONE instruction to each literal program block to
-    // clear the work_done flags so that it's only set if a state has been
-    // switched on for that literal.
-
-    // Note that we add it to every lit program, as they may be
-    // reordered/uniquified by assembleProgramBlocks() above.
-    const bool needs_clear_work = lit_ids.size() > 1 &&
-        any_of_in(lit_ids, [&](u32 lit_id) {
-            return build.literal_info.at(lit_id).squash_group;
-        });
-
     vector<RoseProgram> blocks;
-
     for (const auto &lit_id : lit_ids) {
         auto prog = makeLiteralProgram(build, bc, prog_build, lit_id,
                                        lit_edge_map, false);
-        if (needs_clear_work) {
-            RoseProgram clear_block;
-            clear_block.add_before_end(make_unique<RoseInstrClearWorkDone>());
-            prog.add_block(move(clear_block));
-        }
         blocks.push_back(move(prog));
     }
 
index bca867f096b09157bd241f8c4334619e0373260c..cd9b79c86ace72c8ef7205475aa1b5788168a1ce 100644 (file)
@@ -681,4 +681,13 @@ bool RoseProgramEquivalence::operator()(const RoseProgram &prog1,
     return std::equal(prog1.begin(), prog1.end(), prog2.begin(), is_equiv);
 }
 
+bool reads_work_done_flag(const RoseProgram &prog) {
+    for (const auto &ri : prog) {
+        if (dynamic_cast<const RoseInstrSquashGroups *>(ri.get())) {
+            return true;
+        }
+    }
+    return false;
+}
+
 } // namespace ue2
index 062332318dd3121b482ca745275e09a24c78e52b..d0c67382ac2531ff0825c7655ccf01cd3693c473 100644 (file)
@@ -2348,6 +2348,9 @@ public:
     bool operator()(const RoseProgram &prog1, const RoseProgram &prog2) const;
 };
 
+/** Returns true if the program may read the the interpreter's work_done flag */
+bool reads_work_done_flag(const RoseProgram &prog);
+
 } // namespace ue2
 
 #endif // ROSE_BUILD_PROGRAM_H