mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
rose: minor improvements to avoid unneeded program instructions
- strip out lonely check handled instructions - avoid producing programs for empty ghost roles
This commit is contained in:
parent
88fd95e38a
commit
e24c38a85c
@ -4163,9 +4163,10 @@ void makeRoleEagerEodReports(const RoseBuildImpl &build, build_context &bc,
|
||||
program.add_before_end(move(eod_program));
|
||||
}
|
||||
|
||||
/* Makes a program for a role/vertex given a specfic pred/in_edge. */
|
||||
static
|
||||
RoseProgram makeProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
ProgramBuild &prog_build, const RoseEdge &e) {
|
||||
RoseProgram makeRoleProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
ProgramBuild &prog_build, const RoseEdge &e) {
|
||||
const RoseGraph &g = build.g;
|
||||
auto v = target(e, g);
|
||||
|
||||
@ -4187,10 +4188,11 @@ RoseProgram makeProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
makeRoleCheckBounds(build, v, e, program);
|
||||
}
|
||||
|
||||
// This program may be triggered by different predecessors, with different
|
||||
// offset bounds. We must ensure we put this check/set operation after the
|
||||
// bounds check to deal with this case.
|
||||
// This role program may be triggered by different predecessors, with
|
||||
// different offset bounds. We must ensure we put this check/set operation
|
||||
// after the bounds check to deal with this case.
|
||||
if (in_degree(v, g) > 1) {
|
||||
assert(!build.isRootSuccessor(v));
|
||||
makeRoleCheckNotHandled(prog_build, v, program);
|
||||
}
|
||||
|
||||
@ -4231,6 +4233,12 @@ RoseProgram makeProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
makeRoleEagerEodReports(build, bc, v, eod_block);
|
||||
effects_block.add_block(move(eod_block));
|
||||
|
||||
/* a 'ghost role' may do nothing if we know that its groups are already set
|
||||
* - in this case we can avoid producing a program at all. */
|
||||
if (effects_block.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
program.add_before_end(move(effects_block));
|
||||
return program;
|
||||
}
|
||||
@ -4414,6 +4422,7 @@ void addPredBlockSingle(u32 pred_state, RoseProgram &pred_block,
|
||||
RoseProgram &program) {
|
||||
// Prepend an instruction to check the pred state is on.
|
||||
const auto *end_inst = pred_block.end_instruction();
|
||||
assert(!pred_block.empty());
|
||||
pred_block.insert(begin(pred_block),
|
||||
make_unique<RoseInstrCheckState>(pred_state, end_inst));
|
||||
program.add_block(move(pred_block));
|
||||
@ -4434,6 +4443,12 @@ void addPredBlocksAny(map<u32, RoseProgram> &pred_blocks, u32 num_states,
|
||||
sparse_program.add_before_end(move(ri));
|
||||
|
||||
RoseProgram &block = pred_blocks.begin()->second;
|
||||
assert(!block.empty());
|
||||
|
||||
/* we no longer need the check handled instruction as all the pred-role
|
||||
* blocks are being collapsed together */
|
||||
stripCheckHandledInstruction(block);
|
||||
|
||||
sparse_program.add_before_end(move(block));
|
||||
program.add_block(move(sparse_program));
|
||||
}
|
||||
@ -4491,15 +4506,6 @@ void addPredBlocksMulti(map<u32, RoseProgram> &pred_blocks,
|
||||
static
|
||||
void addPredBlocks(map<u32, RoseProgram> &pred_blocks, u32 num_states,
|
||||
RoseProgram &program) {
|
||||
// Trim empty blocks, if any exist.
|
||||
for (auto it = pred_blocks.begin(); it != pred_blocks.end();) {
|
||||
if (it->second.empty()) {
|
||||
it = pred_blocks.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t num_preds = pred_blocks.size();
|
||||
if (num_preds == 0) {
|
||||
return;
|
||||
@ -4815,8 +4821,10 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
g[target(e, g)].index);
|
||||
assert(contains(bc.roleStateIndices, u));
|
||||
u32 pred_state = bc.roleStateIndices.at(u);
|
||||
pred_blocks[pred_state].add_block(
|
||||
makeProgram(build, bc, prog_build, e));
|
||||
auto role_prog = makeRoleProgram(build, bc, prog_build, e);
|
||||
if (!role_prog.empty()) {
|
||||
pred_blocks[pred_state].add_block(move(role_prog));
|
||||
}
|
||||
}
|
||||
|
||||
// Add blocks to deal with non-root edges (triggered by sparse iterator or
|
||||
@ -4831,7 +4839,7 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
}
|
||||
DEBUG_PRINTF("root edge (%zu,%zu)\n", g[u].index,
|
||||
g[target(e, g)].index);
|
||||
program.add_block(makeProgram(build, bc, prog_build, e));
|
||||
program.add_block(makeRoleProgram(build, bc, prog_build, e));
|
||||
}
|
||||
|
||||
if (lit_id == build.eod_event_literal_id) {
|
||||
@ -4872,6 +4880,7 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
||||
if (contains(lit_edge_map, lit_id)) {
|
||||
edges_ptr = &lit_edge_map.at(lit_id);
|
||||
} else {
|
||||
/* literal may happen only in a delay context */
|
||||
edges_ptr = &no_edges;
|
||||
}
|
||||
|
||||
@ -5205,7 +5214,8 @@ pair<u32, u32> writeAnchoredPrograms(const RoseBuildImpl &build,
|
||||
auto it = cache.find(offset);
|
||||
if (it != end(cache)) {
|
||||
anch_id = it->second;
|
||||
DEBUG_PRINTF("reusing anch_id %u for offset %u\n", anch_id, offset);
|
||||
DEBUG_PRINTF("reusing anch_id %u for offset %u\n", anch_id,
|
||||
offset);
|
||||
} else {
|
||||
anch_id = verify_u32(programs.size());
|
||||
programs.push_back(offset);
|
||||
|
@ -639,6 +639,11 @@ OffsetMap makeOffsetMap(const RoseProgram &program, u32 *total_len) {
|
||||
return offset_map;
|
||||
}
|
||||
|
||||
RoseProgram::iterator RoseProgram::erase(RoseProgram::iterator first,
|
||||
RoseProgram::iterator last) {
|
||||
return prog.erase(first, last);
|
||||
}
|
||||
|
||||
bytecode_ptr<char> writeProgram(RoseEngineBlob &blob,
|
||||
const RoseProgram &program) {
|
||||
u32 total_len = 0;
|
||||
@ -681,6 +686,28 @@ bool RoseProgramEquivalence::operator()(const RoseProgram &prog1,
|
||||
return std::equal(prog1.begin(), prog1.end(), prog2.begin(), is_equiv);
|
||||
}
|
||||
|
||||
void stripCheckHandledInstruction(RoseProgram &prog) {
|
||||
for (auto it = prog.begin(); it != prog.end();) {
|
||||
auto ins = dynamic_cast<const RoseInstrCheckNotHandled *>(it->get());
|
||||
if (!ins) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto next_it = next(it);
|
||||
assert(next_it != prog.end()); /* there should always be an end ins */
|
||||
auto next_ins = next_it->get();
|
||||
|
||||
/* update all earlier instructions which point to ins to instead point
|
||||
* to the next instruction. Only need to look at earlier as we only ever
|
||||
* jump forward. */
|
||||
RoseProgram::update_targets(prog.begin(), it, ins, next_ins);
|
||||
|
||||
/* remove check handled instruction */
|
||||
it = prog.erase(it, next_it);
|
||||
}
|
||||
}
|
||||
|
||||
bool reads_work_done_flag(const RoseProgram &prog) {
|
||||
for (const auto &ri : prog) {
|
||||
if (dynamic_cast<const RoseInstrSquashGroups *>(ri.get())) {
|
||||
|
@ -2219,7 +2219,6 @@ public:
|
||||
return prog.back().get();
|
||||
}
|
||||
|
||||
private:
|
||||
static void update_targets(iterator it, iterator it_end,
|
||||
const RoseInstruction *old_target,
|
||||
const RoseInstruction *new_target) {
|
||||
@ -2231,7 +2230,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
iterator insert(iterator it, std::unique_ptr<RoseInstruction> ri) {
|
||||
assert(!prog.empty());
|
||||
assert(it != end());
|
||||
@ -2267,6 +2265,10 @@ public:
|
||||
return it;
|
||||
}
|
||||
|
||||
/* Note: takes iterator rather than const_iterator to support toolchains
|
||||
* with pre-C++11 standard libraries (i.e., gcc-4.8). */
|
||||
iterator erase(iterator first, iterator last);
|
||||
|
||||
/**
|
||||
* \brief Adds this instruction to the program just before the terminating
|
||||
* ROSE_INSTR_END.
|
||||
@ -2348,6 +2350,9 @@ public:
|
||||
bool operator()(const RoseProgram &prog1, const RoseProgram &prog2) const;
|
||||
};
|
||||
|
||||
/* Removes any CHECK_HANDLED instructions from the given program */
|
||||
void stripCheckHandledInstruction(RoseProgram &prog);
|
||||
|
||||
/** Returns true if the program may read the the interpreter's work_done flag */
|
||||
bool reads_work_done_flag(const RoseProgram &prog);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user