return progress;
}
-bool
-fs_visitor::register_coalesce()
-{
- bool progress = false;
- int if_depth = 0;
- int loop_depth = 0;
-
- foreach_list_safe(node, &this->instructions) {
- fs_inst *inst = (fs_inst *)node;
-
- /* Make sure that we dominate the instructions we're going to
- * scan for interfering with our coalescing, or we won't have
- * scanned enough to see if anything interferes with our
- * coalescing. We don't dominate the following instructions if
- * we're in a loop or an if block.
- */
- switch (inst->opcode) {
- case BRW_OPCODE_DO:
- loop_depth++;
- break;
- case BRW_OPCODE_WHILE:
- loop_depth--;
- break;
- case BRW_OPCODE_IF:
- if_depth++;
- break;
- case BRW_OPCODE_ENDIF:
- if_depth--;
- break;
- default:
- break;
- }
- if (loop_depth || if_depth)
- continue;
-
- if (inst->opcode != BRW_OPCODE_MOV ||
- inst->is_partial_write() ||
- inst->saturate ||
- inst->dst.file != GRF || (inst->src[0].file != GRF &&
- inst->src[0].file != UNIFORM)||
- inst->dst.type != inst->src[0].type)
- continue;
-
- bool has_source_modifiers = (inst->src[0].abs ||
- inst->src[0].negate ||
- inst->src[0].smear != -1 ||
- inst->src[0].file == UNIFORM);
-
- /* Found a move of a GRF to a GRF. Let's see if we can coalesce
- * them: check for no writes to either one until the exit of the
- * program.
- */
- bool interfered = false;
-
- for (fs_inst *scan_inst = (fs_inst *)inst->next;
- !scan_inst->is_tail_sentinel();
- scan_inst = (fs_inst *)scan_inst->next) {
- if (scan_inst->dst.file == GRF) {
- if (scan_inst->overwrites_reg(inst->dst) ||
- scan_inst->overwrites_reg(inst->src[0])) {
- interfered = true;
- break;
- }
- }
-
- if (has_source_modifiers) {
- for (int i = 0; i < 3; i++) {
- if (scan_inst->src[i].file == GRF &&
- scan_inst->src[i].reg == inst->dst.reg &&
- scan_inst->src[i].reg_offset == inst->dst.reg_offset &&
- inst->dst.type != scan_inst->src[i].type)
- {
- interfered = true;
- break;
- }
- }
- }
-
-
- /* The gen6 MATH instruction can't handle source modifiers or
- * unusual register regions, so avoid coalescing those for
- * now. We should do something more specific.
- */
- if (has_source_modifiers && !can_do_source_mods(scan_inst)) {
- interfered = true;
- break;
- }
-
- if (scan_inst->mlen > 0 && scan_inst->base_mrf == -1 &&
- scan_inst->src[0].file == GRF &&
- scan_inst->src[0].reg == inst->dst.reg) {
- interfered = true;
- break;
- }
-
- /* The accumulator result appears to get used for the
- * conditional modifier generation. When negating a UD
- * value, there is a 33rd bit generated for the sign in the
- * accumulator value, so now you can't check, for example,
- * equality with a 32-bit value. See piglit fs-op-neg-uint.
- */
- if (scan_inst->conditional_mod &&
- inst->src[0].negate &&
- inst->src[0].type == BRW_REGISTER_TYPE_UD) {
- interfered = true;
- break;
- }
- }
- if (interfered) {
- continue;
- }
-
- /* Rewrite the later usage to point at the source of the move to
- * be removed.
- */
- for (fs_inst *scan_inst = inst;
- !scan_inst->is_tail_sentinel();
- scan_inst = (fs_inst *)scan_inst->next) {
- for (int i = 0; i < 3; i++) {
- if (scan_inst->src[i].file == GRF &&
- scan_inst->src[i].reg == inst->dst.reg &&
- scan_inst->src[i].reg_offset == inst->dst.reg_offset) {
- fs_reg new_src = inst->src[0];
- new_src.type = scan_inst->src[i].type;
- if (scan_inst->src[i].abs) {
- new_src.negate = 0;
- new_src.abs = 1;
- }
- new_src.negate ^= scan_inst->src[i].negate;
- new_src.sechalf = scan_inst->src[i].sechalf;
- scan_inst->src[i] = new_src;
- }
- }
- }
-
- inst->remove();
- progress = true;
- }
-
- if (progress)
- invalidate_live_intervals();
-
- return progress;
-}
-
-
bool
fs_visitor::compute_to_mrf()
{
progress = dead_code_eliminate() || progress;
progress = dead_code_eliminate_local() || progress;
progress = dead_control_flow_eliminate(this) || progress;
- progress = register_coalesce() || progress;
progress = register_coalesce_2() || progress;
progress = compute_to_mrf() || progress;
} while (progress);