be more selective about generating CLEAR_WORK_DONE instructions

This commit is contained in:
Alex Coyte 2017-04-11 10:50:16 +10:00 committed by Matthew Barr
parent cd424bdb45
commit a810bac8f7
3 changed files with 29 additions and 22 deletions

View 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));
}

View 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

View 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