static bool qir_opt_peephole_sf_block(struct vc4_compile *c, struct qblock *block) { bool progress = false; /* We don't have liveness dataflow analysis for flags, but we also * never generate a use of flags across control flow, so just treat * them as unused at block exit. */ bool sf_live = false; struct qinst *last_sf = NULL; /* Walk the block from bottom to top, tracking if the SF is used, and * removing unused or repeated ones. */ qir_for_each_inst_rev(inst, block) { if (inst->sf) { if (!sf_live) { /* Our instruction's SF isn't read, so drop it. */ dump_from(c, inst, "dead SF"); inst->sf = false; dump_to(c, inst); progress = true; } else if (last_sf && inst_result_equals(last_sf, inst)) { /* The last_sf sets up same value as inst, so * just drop the later one. */ dump_from(c, last_sf, "repeated SF"); last_sf->sf = false; dump_to(c, last_sf); progress = true; last_sf = inst; } else { last_sf = inst; } sf_live = false; } if (last_sf) { if (inst_srcs_updated(last_sf, inst)) last_sf = NULL; } if (qir_depends_on_flags(inst)) sf_live = true; } return progress; }
bool qir_opt_peephole_sf(struct vc4_compile *c) { bool progress = false; bool sf_live = false; struct qinst *last_sf = NULL; /* Walk the block from bottom to top, tracking if the SF is used, and * removing unused or repeated ones. */ list_for_each_entry_rev(struct qinst, inst, &c->instructions, link) { if (inst->sf) { if (!sf_live) { /* Our instruction's SF isn't read, so drop it. */ dump_from(c, inst, "dead SF"); inst->sf = false; dump_to(c, inst); progress = true; } else if (last_sf && inst_result_equals(last_sf, inst)) { /* The last_sf sets up same value as inst, so * just drop the later one. */ dump_from(c, last_sf, "repeated SF"); last_sf->sf = false; dump_to(c, last_sf); progress = true; last_sf = inst; } else { last_sf = inst; } sf_live = false; } if (last_sf) { if (inst_srcs_updated(last_sf, inst)) last_sf = NULL; } if (qir_depends_on_flags(inst)) sf_live = true; } return progress; }