/** * Emit a typed surface read opcode. \p dims determines the number of * components of the address and \p size the number of components of the * returned value. */ fs_reg emit_typed_read(const fs_builder &bld, const fs_reg &surface, const fs_reg &addr, unsigned dims, unsigned size) { return emit_send(bld, SHADER_OPCODE_TYPED_SURFACE_READ_LOGICAL, addr, fs_reg(), surface, dims, size, size); }
void brw_blorp_eu_emitter::emit_texture_lookup(const struct brw_reg &dst, enum opcode op, unsigned base_mrf, unsigned msg_length) { fs_inst *inst = new (mem_ctx) fs_inst(op, dst, brw_message_reg(base_mrf), fs_reg(0u)); inst->base_mrf = base_mrf; inst->mlen = msg_length; inst->header_size = 0; insts.push_tail(inst); }
bool fs_visitor::opt_cse_local(bblock_t *block, exec_list *aeb) { bool progress = false; void *mem_ctx = ralloc_context(this->mem_ctx); for (fs_inst *inst = (fs_inst *)block->start; inst != block->end->next; inst = (fs_inst *) inst->next) { /* Skip some cases. */ if (is_expression(inst) && !inst->predicate && inst->mlen == 0 && !inst->force_uncompressed && !inst->force_sechalf && !inst->conditional_mod) { bool found = false; aeb_entry *entry; foreach_list(entry_node, aeb) { entry = (aeb_entry *) entry_node; /* Match current instruction's expression against those in AEB. */ if (inst->opcode == entry->generator->opcode && inst->saturate == entry->generator->saturate && operands_match(entry->generator->src, inst->src)) { found = true; progress = true; break; } } if (!found) { /* Our first sighting of this expression. Create an entry. */ aeb_entry *entry = ralloc(mem_ctx, aeb_entry); entry->tmp = reg_undef; entry->generator = inst; aeb->push_tail(entry); } else { /* This is at least our second sighting of this expression. * If we don't have a temporary already, make one. */ bool no_existing_temp = entry->tmp.file == BAD_FILE; if (no_existing_temp) { entry->tmp = fs_reg(this, glsl_type::float_type); entry->tmp.type = inst->dst.type; fs_inst *copy = new(ralloc_parent(inst)) fs_inst(BRW_OPCODE_MOV, entry->generator->dst, entry->tmp); entry->generator->insert_after(copy); entry->generator->dst = entry->tmp; } /* dest <- temp */ fs_inst *copy = new(ralloc_parent(inst)) fs_inst(BRW_OPCODE_MOV, inst->dst, entry->tmp); inst->replace_with(copy); /* Appending an instruction may have changed our bblock end. */ if (inst == block->end) { block->end = copy; } /* Continue iteration with copy->next */ inst = copy; } }
bool fs_visitor::dead_code_eliminate() { bool progress = false; calculate_live_intervals(); int num_vars = live_intervals->num_vars; BITSET_WORD *live = ralloc_array(NULL, BITSET_WORD, BITSET_WORDS(num_vars)); foreach_block (block, cfg) { memcpy(live, live_intervals->bd[block->num].liveout, sizeof(BITSET_WORD) * BITSET_WORDS(num_vars)); foreach_inst_in_block_reverse(fs_inst, inst, block) { if (inst->dst.file == GRF && !inst->has_side_effects() && !inst->writes_flag()) { bool result_live = false; if (inst->regs_written == 1) { int var = live_intervals->var_from_reg(&inst->dst); result_live = BITSET_TEST(live, var); } else { int var = live_intervals->var_from_vgrf[inst->dst.reg]; for (int i = 0; i < inst->regs_written; i++) { result_live = result_live || BITSET_TEST(live, var + i); } } if (!result_live) { progress = true; if (inst->writes_accumulator) { inst->dst = fs_reg(retype(brw_null_reg(), inst->dst.type)); } else { inst->opcode = BRW_OPCODE_NOP; continue; } } } if (inst->dst.file == GRF) { if (!inst->is_partial_write()) { int var = live_intervals->var_from_vgrf[inst->dst.reg]; for (int i = 0; i < inst->regs_written; i++) { BITSET_CLEAR(live, var + inst->dst.reg_offset + i); } } } for (int i = 0; i < inst->sources; i++) { if (inst->src[i].file == GRF) { int var = live_intervals->var_from_vgrf[inst->src[i].reg]; for (int j = 0; j < inst->regs_read(this, i); j++) { BITSET_SET(live, var + inst->src[i].reg_offset + j); } } } } }
bool fs_visitor::opt_cse_local(bblock_t *block, exec_list *aeb) { bool progress = false; void *cse_ctx = ralloc_context(NULL); int ip = block->start_ip; for (fs_inst *inst = (fs_inst *)block->start; inst != block->end->next; inst = (fs_inst *) inst->next) { /* Skip some cases. */ if (is_expression(inst) && !inst->is_partial_write() && (inst->dst.file != HW_REG || inst->dst.is_null())) { bool found = false; aeb_entry *entry; foreach_list(entry_node, aeb) { entry = (aeb_entry *) entry_node; /* Match current instruction's expression against those in AEB. */ if (instructions_match(inst, entry->generator)) { found = true; progress = true; break; } } if (!found) { /* Our first sighting of this expression. Create an entry. */ aeb_entry *entry = ralloc(cse_ctx, aeb_entry); entry->tmp = reg_undef; entry->generator = inst; aeb->push_tail(entry); } else { /* This is at least our second sighting of this expression. * If we don't have a temporary already, make one. */ bool no_existing_temp = entry->tmp.file == BAD_FILE; if (no_existing_temp && !entry->generator->dst.is_null()) { int written = entry->generator->regs_written; fs_reg orig_dst = entry->generator->dst; fs_reg tmp = fs_reg(GRF, virtual_grf_alloc(written), orig_dst.type); entry->tmp = tmp; entry->generator->dst = tmp; fs_inst *copy; if (written > 1) { fs_reg *sources = ralloc_array(mem_ctx, fs_reg, written); for (int i = 0; i < written; i++) { sources[i] = tmp; sources[i].reg_offset = i; } copy = LOAD_PAYLOAD(orig_dst, sources, written); } else { copy = MOV(orig_dst, tmp); copy->force_writemask_all = entry->generator->force_writemask_all; } entry->generator->insert_after(copy); } /* dest <- temp */ if (!inst->dst.is_null()) { int written = inst->regs_written; assert(written == entry->generator->regs_written); assert(inst->dst.type == entry->tmp.type); fs_reg dst = inst->dst; fs_reg tmp = entry->tmp; fs_inst *copy; if (written > 1) { fs_reg *sources = ralloc_array(mem_ctx, fs_reg, written); for (int i = 0; i < written; i++) { sources[i] = tmp; sources[i].reg_offset = i; } copy = LOAD_PAYLOAD(dst, sources, written); } else { copy = MOV(dst, tmp); copy->force_writemask_all = inst->force_writemask_all; } inst->insert_before(copy); } /* Set our iterator so that next time through the loop inst->next * will get the instruction in the basic block after the one we've * removed. */ fs_inst *prev = (fs_inst *)inst->prev; inst->remove(); /* Appending an instruction may have changed our bblock end. */ if (inst == block->end) { block->end = prev; } inst = prev; } }
bool fs_visitor::opt_cse_local(bblock_t *block, exec_list *aeb) { bool progress = false; void *mem_ctx = ralloc_context(this->mem_ctx); int ip = block->start_ip; for (fs_inst *inst = (fs_inst *)block->start; inst != block->end->next; inst = (fs_inst *) inst->next) { /* Skip some cases. */ if (is_expression(inst) && !inst->predicate && !inst->is_partial_write() && !inst->conditional_mod) { bool found = false; aeb_entry *entry; foreach_list(entry_node, aeb) { entry = (aeb_entry *) entry_node; /* Match current instruction's expression against those in AEB. */ if (inst->opcode == entry->generator->opcode && inst->saturate == entry->generator->saturate && inst->dst.type == entry->generator->dst.type && operands_match(entry->generator->src, inst->src)) { found = true; progress = true; break; } } if (!found) { /* Our first sighting of this expression. Create an entry. */ aeb_entry *entry = ralloc(mem_ctx, aeb_entry); entry->tmp = reg_undef; entry->generator = inst; aeb->push_tail(entry); } else { /* This is at least our second sighting of this expression. * If we don't have a temporary already, make one. */ bool no_existing_temp = entry->tmp.file == BAD_FILE; if (no_existing_temp) { int written = entry->generator->regs_written; fs_reg orig_dst = entry->generator->dst; fs_reg tmp = fs_reg(GRF, virtual_grf_alloc(written), orig_dst.type); entry->tmp = tmp; entry->generator->dst = tmp; for (int i = 0; i < written; i++) { fs_inst *copy = MOV(orig_dst, tmp); copy->force_writemask_all = entry->generator->force_writemask_all; entry->generator->insert_after(copy); orig_dst.reg_offset++; tmp.reg_offset++; } } /* dest <- temp */ int written = inst->regs_written; assert(written == entry->generator->regs_written); assert(inst->dst.type == entry->tmp.type); fs_reg dst = inst->dst; fs_reg tmp = entry->tmp; fs_inst *copy = NULL; for (int i = 0; i < written; i++) { copy = MOV(dst, tmp); copy->force_writemask_all = inst->force_writemask_all; inst->insert_before(copy); dst.reg_offset++; tmp.reg_offset++; } inst->remove(); /* Appending an instruction may have changed our bblock end. */ if (inst == block->end) { block->end = copy; } /* Continue iteration with copy->next */ inst = copy; } }