static void schedule_block(struct r300_fragment_program_compiler * c,
		struct rc_instruction * begin, struct rc_instruction * end)
{
	struct schedule_state s;
	unsigned int ip;

	memset(&s, 0, sizeof(s));
	s.C = &c->Base;

	/* Scan instructions for data dependencies */
	ip = 0;
	for(struct rc_instruction * inst = begin; inst != end; inst = inst->Next) {
		s.Current = memory_pool_malloc(&c->Base.Pool, sizeof(*s.Current));
		memset(s.Current, 0, sizeof(struct schedule_instruction));

		s.Current->Instruction = inst;
		inst->IP = ip++;

		DBG("%i: Scanning\n", inst->IP);

		/* The order of things here is subtle and maybe slightly
		 * counter-intuitive, to account for the case where an
		 * instruction writes to the same register as it reads
		 * from. */
		rc_for_all_writes_chan(inst, &scan_write, &s);
		rc_for_all_reads_chan(inst, &scan_read, &s);

		DBG("%i: Has %i dependencies\n", inst->IP, s.Current->NumDependencies);

		if (!s.Current->NumDependencies)
			instruction_ready(&s, s.Current);

		/* Get global readers for possible RGB->Alpha conversion. */
		rc_get_readers(s.C, inst, &s.Current->GlobalReaders,
				is_rgb_to_alpha_possible_normal,
				is_rgb_to_alpha_possible, NULL);
	}

	/* Temporarily unlink all instructions */
	begin->Prev->Next = end;
	end->Prev = begin->Prev;

	/* Schedule instructions back */
	while(!s.C->Error &&
	      (s.ReadyTEX || s.ReadyRGB || s.ReadyAlpha || s.ReadyFullALU)) {
		if (s.ReadyTEX)
			emit_all_tex(&s, end);

		while(!s.C->Error && (s.ReadyFullALU || s.ReadyRGB || s.ReadyAlpha))
			emit_one_alu(&s, end);
	}
}
Exemplo n.º 2
0
/**
 * This function renames registers in an attempt to get the code close to
 * SSA form.  After this function has completed, most of the register are only
 * written to one time, with a few exceptions.
 *
 * This function assumes all the instructions are still of type
 * RC_INSTRUCTION_NORMAL.
 */
void rc_rename_regs(struct radeon_compiler *c, void *user)
{
	unsigned int i, used_length;
	int new_index;
	struct rc_instruction * inst;
	struct rc_reader_data reader_data;
	unsigned char * used;

	/* XXX Remove this once the register allocation works with flow control. */
	for(inst = c->Program.Instructions.Next;
					inst != &c->Program.Instructions;
					inst = inst->Next) {
		if (inst->U.I.Opcode == RC_OPCODE_BGNLOOP)
			return;
	}

	used_length = 2 * rc_recompute_ips(c);
	used = memory_pool_malloc(&c->Pool, sizeof(unsigned char) * used_length);
	memset(used, 0, sizeof(unsigned char) * used_length);

	rc_get_used_temporaries(c, used, used_length);
	for(inst = c->Program.Instructions.Next;
					inst != &c->Program.Instructions;
					inst = inst->Next) {

		if (inst->U.I.DstReg.File != RC_FILE_TEMPORARY)
			continue;

		reader_data.ExitOnAbort = 1;
		rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL);

		if (reader_data.Abort || reader_data.ReaderCount == 0)
			continue;

		new_index = rc_find_free_temporary_list(c, used, used_length,
						RC_MASK_XYZW);
		if (new_index < 0) {
			rc_error(c, "Ran out of temporary registers\n");
			return;
		}

		reader_data.Writer->U.I.DstReg.Index = new_index;
		for(i = 0; i < reader_data.ReaderCount; i++) {
			reader_data.Readers[i].U.I.Src->Index = new_index;
		}
	}
}
static void schedule_block(struct schedule_state * s,
		struct rc_instruction * begin, struct rc_instruction * end)
{
	unsigned int ip;

	/* Scan instructions for data dependencies */
	ip = 0;
	for(struct rc_instruction * inst = begin; inst != end; inst = inst->Next) {
		s->Current = memory_pool_malloc(&s->C->Pool, sizeof(*s->Current));
		memset(s->Current, 0, sizeof(struct schedule_instruction));

		if (inst->Type == RC_INSTRUCTION_NORMAL) {
			const struct rc_opcode_info * info =
					rc_get_opcode_info(inst->U.I.Opcode);
			if (info->HasTexture) {
				s->TEXCount++;
			}
		}

		/* XXX: This causes SemWait to be set for all instructions in
		 * a block if the previous block contained a TEX instruction.
		 * We can do better here, but it will take a lot of work. */
		if (s->PrevBlockHasTex) {
			s->Current->TexReadCount = 1;
		}

		s->Current->Instruction = inst;
		inst->IP = ip++;

		DBG("%i: Scanning\n", inst->IP);

		/* The order of things here is subtle and maybe slightly
		 * counter-intuitive, to account for the case where an
		 * instruction writes to the same register as it reads
		 * from. */
		rc_for_all_writes_chan(inst, &scan_write, s);
		rc_for_all_reads_chan(inst, &scan_read, s);

		DBG("%i: Has %i dependencies\n", inst->IP, s->Current->NumDependencies);

		if (!s->Current->NumDependencies) {
			instruction_ready(s, s->Current);
		}

		/* Get global readers for possible RGB->Alpha conversion. */
		s->Current->GlobalReaders.ExitOnAbort = 1;
		rc_get_readers(s->C, inst, &s->Current->GlobalReaders,
				is_rgb_to_alpha_possible_normal,
				is_rgb_to_alpha_possible, NULL);
	}

	/* Temporarily unlink all instructions */
	begin->Prev->Next = end;
	end->Prev = begin->Prev;

	/* Schedule instructions back */
	while(!s->C->Error &&
	      (s->ReadyTEX || s->ReadyRGB || s->ReadyAlpha || s->ReadyFullALU)) {
		emit_instruction(s, end);
	}
}