summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/compiler/radeon_pair_schedule.c149
1 files changed, 99 insertions, 50 deletions
diff --git a/src/gallium/drivers/r300/compiler/radeon_pair_schedule.c b/src/gallium/drivers/r300/compiler/radeon_pair_schedule.c
index fb1b86163a6..1f589cdb98e 100644
--- a/src/gallium/drivers/r300/compiler/radeon_pair_schedule.c
+++ b/src/gallium/drivers/r300/compiler/radeon_pair_schedule.c
@@ -60,6 +60,11 @@ struct schedule_instruction {
* "all readers"), even those outside the basic block this instruction
* lives in. */
struct rc_reader_data GlobalReaders;
+
+ /** If the scheduler has paired an RGB and an Alpha instruction together,
+ * PairedInst references the alpha insturction's dependency information.
+ */
+ struct schedule_instruction * PairedInst;
};
@@ -142,6 +147,25 @@ static struct reg_value ** get_reg_valuep(struct schedule_state * s,
return &s->Temporary[index].Values[chan];
}
+static void remove_inst_from_list(struct schedule_instruction ** list,
+ struct schedule_instruction * inst)
+{
+ struct schedule_instruction * prev = NULL;
+ struct schedule_instruction * list_ptr;
+ for (list_ptr = *list; list_ptr; prev = list_ptr,
+ list_ptr = list_ptr->NextReady) {
+ if (list_ptr == inst) {
+ if (prev) {
+ prev->NextReady = inst->NextReady;
+ } else {
+ *list = inst->NextReady;
+ }
+ inst->NextReady = NULL;
+ break;
+ }
+ }
+}
+
static void add_inst_to_list(struct schedule_instruction ** list, struct schedule_instruction * inst)
{
inst->NextReady = *list;
@@ -202,6 +226,9 @@ static void commit_update_reads(struct schedule_state * s,
decrease_dependencies(s, v->Next->Writer);
}
}
+ if (sinst->PairedInst) {
+ commit_update_reads(s, sinst->PairedInst);
+ }
}
static void commit_update_writes(struct schedule_state * s,
@@ -224,6 +251,9 @@ static void commit_update_writes(struct schedule_state * s,
decrease_dependencies(s, v->Next->Writer);
}
}
+ if (sinst->PairedInst) {
+ commit_update_writes(s, sinst->PairedInst);
+ }
}
static void commit_alu_instruction(struct schedule_state * s, struct schedule_instruction * sinst)
@@ -480,6 +510,7 @@ static int merge_instructions(struct rc_pair_instruction * rgb, struct rc_pair_i
|| (rgb->RGB.OutputWriteMask && alpha->WriteALUResult)) {
return 0;
}
+
memcpy(&backup, rgb, sizeof(struct rc_pair_instruction));
if (destructive_merge_instructions(rgb, alpha))
@@ -748,6 +779,71 @@ static int convert_rgb_to_alpha(
}
/**
+ * This function attempts to merge RGB and Alpha instructions together.
+ */
+static void pair_instructions(struct schedule_state * s)
+{
+ struct schedule_instruction *rgb_ptr;
+ struct schedule_instruction *alpha_ptr;
+
+ /* Some pairings might fail because they require too
+ * many source slots; try all possible pairings if necessary */
+ rgb_ptr = s->ReadyRGB;
+ while(rgb_ptr) {
+ struct schedule_instruction * rgb_next = rgb_ptr->NextReady;
+ alpha_ptr = s->ReadyAlpha;
+ while(alpha_ptr) {
+ struct schedule_instruction * alpha_next = alpha_ptr->NextReady;
+ if (merge_instructions(&rgb_ptr->Instruction->U.P, &alpha_ptr->Instruction->U.P)) {
+ /* Remove RGB and Alpha from their ready lists.
+ */
+ remove_inst_from_list(&s->ReadyRGB, rgb_ptr);
+ remove_inst_from_list(&s->ReadyAlpha, alpha_ptr);
+ rgb_ptr->PairedInst = alpha_ptr;
+ add_inst_to_list(&s->ReadyFullALU, rgb_ptr);
+ break;
+ }
+ alpha_ptr = alpha_next;
+ }
+ rgb_ptr = rgb_next;
+ }
+
+ /* Try to convert some of the RGB instructions to Alpha and
+ * try to pair it with another RGB. */
+ rgb_ptr = s->ReadyRGB;
+ while (rgb_ptr && s->ReadyRGB && s->ReadyRGB->NextReady) {
+ int paired = 0;
+ if (rgb_ptr->NumWriteValues == 1
+ && convert_rgb_to_alpha(s, rgb_ptr)) {
+
+ struct schedule_instruction * pair_ptr;
+ for (pair_ptr = s->ReadyRGB; pair_ptr;
+ pair_ptr = pair_ptr->NextReady) {
+ if (pair_ptr == rgb_ptr) {
+ continue;
+ }
+ if (merge_instructions(&pair_ptr->Instruction->U.P,
+ &rgb_ptr->Instruction->U.P)) {
+ remove_inst_from_list(&s->ReadyRGB, rgb_ptr);
+ remove_inst_from_list(&s->ReadyRGB, pair_ptr);
+ pair_ptr->PairedInst = rgb_ptr;
+
+ add_inst_to_list(&s->ReadyFullALU, pair_ptr);
+ rgb_ptr = s->ReadyRGB;
+ paired = 1;
+ break;
+ }
+
+ }
+ }
+ if (!paired) {
+ rgb_ptr = rgb_ptr->NextReady;
+ }
+ }
+}
+
+
+/**
* Find a good ALU instruction or pair of ALU instruction and emit it.
*
* Prefer emitting full ALU instructions, so that when we reach a point
@@ -758,61 +854,15 @@ static void emit_one_alu(struct schedule_state *s, struct rc_instruction * befor
{
struct schedule_instruction * sinst;
+ /* Try to merge RGB and Alpha instructions together. */
+ pair_instructions(s);
+
if (s->ReadyFullALU) {
sinst = s->ReadyFullALU;
s->ReadyFullALU = s->ReadyFullALU->NextReady;
rc_insert_instruction(before->Prev, sinst->Instruction);
commit_alu_instruction(s, sinst);
} else {
- struct schedule_instruction **prgb;
- struct schedule_instruction **palpha;
- struct schedule_instruction *prev;
-pair:
- /* Some pairings might fail because they require too
- * many source slots; try all possible pairings if necessary */
- for(prgb = &s->ReadyRGB; *prgb; prgb = &(*prgb)->NextReady) {
- for(palpha = &s->ReadyAlpha; *palpha; palpha = &(*palpha)->NextReady) {
- struct schedule_instruction * psirgb = *prgb;
- struct schedule_instruction * psialpha = *palpha;
-
- if (!merge_instructions(&psirgb->Instruction->U.P, &psialpha->Instruction->U.P))
- continue;
-
- *prgb = (*prgb)->NextReady;
- *palpha = (*palpha)->NextReady;
- rc_insert_instruction(before->Prev, psirgb->Instruction);
- commit_alu_instruction(s, psirgb);
- commit_alu_instruction(s, psialpha);
- goto success;
- }
- }
- prev = NULL;
- /* No success in pairing, now try to convert one of the RGB
- * instructions to an Alpha so we can pair it with another RGB.
- */
- if (s->ReadyRGB && s->ReadyRGB->NextReady) {
- for(prgb = &s->ReadyRGB; *prgb; prgb = &(*prgb)->NextReady) {
- if ((*prgb)->NumWriteValues == 1) {
- struct schedule_instruction * prgb_next;
- if (!convert_rgb_to_alpha(s, *prgb))
- goto cont_loop;
- prgb_next = (*prgb)->NextReady;
- /* Add instruction to the Alpha ready list. */
- (*prgb)->NextReady = s->ReadyAlpha;
- s->ReadyAlpha = *prgb;
- /* Remove instruction from the RGB ready list.*/
- if (prev)
- prev->NextReady = prgb_next;
- else
- s->ReadyRGB = prgb_next;
- goto pair;
- }
-cont_loop:
- prev = *prgb;
- }
- }
- /* Still no success in pairing, just take the first RGB
- * or alpha instruction. */
if (s->ReadyRGB) {
sinst = s->ReadyRGB;
s->ReadyRGB = s->ReadyRGB->NextReady;
@@ -826,7 +876,6 @@ cont_loop:
rc_insert_instruction(before->Prev, sinst->Instruction);
commit_alu_instruction(s, sinst);
- success: ;
}
/* If the instruction we just emitted uses a presubtract value, and
* the presubtract sources were written by the previous intstruction,