Esempio n. 1
0
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;
         }
      }
Esempio n. 2
0
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;
	 }
      }