r300/compiler: Try to eliminate REPL_ALPHA instructions
authorTom Stellard <tstellar@gmail.com>
Sat, 15 Oct 2011 21:56:15 +0000 (17:56 -0400)
committerTom Stellard <tstellar@gmail.com>
Mon, 17 Oct 2011 02:54:48 +0000 (19:54 -0700)
Scalar instruction that need to write to the xyz components of a
register must reserve the RGB instruction slot for a REPL_ALPHA
instruction.  With this commit, the scheduler will attempt to free
the RGB slot by moving the write to the w component of a register.

src/gallium/drivers/r300/compiler/radeon_pair_schedule.c

index 94cf9a77cea5e06faa026d0a9ec9e7f294935f9e..b3b0f6fc25bf2873afe06200e74f01eac536a671 100644 (file)
@@ -896,7 +896,16 @@ static int convert_rgb_to_alpha(
                return 0;
        }
 
-       pair_inst->Alpha.Opcode = pair_inst->RGB.Opcode;
+       /* If we are converting a full instruction with RC_OPCODE_REPL_ALPHA
+        * as the RGB opcode, then the Alpha instruction will already contain
+        * the correct opcode and instruction args, so we do not want to
+        * overwrite them.
+        */
+       if (pair_inst->RGB.Opcode != RC_OPCODE_REPL_ALPHA) {
+               pair_inst->Alpha.Opcode = pair_inst->RGB.Opcode;
+               memcpy(pair_inst->Alpha.Arg, pair_inst->RGB.Arg,
+                                               sizeof(pair_inst->Alpha.Arg));
+       }
        pair_inst->Alpha.DestIndex = new_index;
        pair_inst->Alpha.WriteMask = RC_MASK_W;
        pair_inst->Alpha.Target = pair_inst->RGB.Target;
@@ -904,8 +913,6 @@ static int convert_rgb_to_alpha(
        pair_inst->Alpha.DepthWriteMask = pair_inst->RGB.DepthWriteMask;
        pair_inst->Alpha.Saturate = pair_inst->RGB.Saturate;
        pair_inst->Alpha.Omod = pair_inst->RGB.Omod;
-       memcpy(pair_inst->Alpha.Arg, pair_inst->RGB.Arg,
-                                               sizeof(pair_inst->Alpha.Arg));
        /* Move the swizzles into the first chan */
        for (i = 0; i < info->NumSrcRegs; i++) {
                unsigned int j;
@@ -935,6 +942,48 @@ static int convert_rgb_to_alpha(
        return 1;
 }
 
+static void try_convert_and_pair(
+       struct schedule_state *s,
+       struct schedule_instruction ** inst_list)
+{
+       struct schedule_instruction * list_ptr = *inst_list;
+       while (list_ptr && *inst_list && (*inst_list)->NextReady) {
+               int paired = 0;
+               if (list_ptr->Instruction->U.P.Alpha.Opcode != RC_OPCODE_NOP
+                       && list_ptr->Instruction->U.P.RGB.Opcode
+                                               != RC_OPCODE_REPL_ALPHA) {
+                               goto next;
+               }
+               if (list_ptr->NumWriteValues == 1
+                                       && convert_rgb_to_alpha(s, list_ptr)) {
+
+                       struct schedule_instruction * pair_ptr;
+                       remove_inst_from_list(inst_list, list_ptr);
+                       add_inst_to_list_score(&s->ReadyAlpha, list_ptr);
+
+                       for (pair_ptr = s->ReadyRGB; pair_ptr;
+                                       pair_ptr = pair_ptr->NextReady) {
+                               if (merge_instructions(&pair_ptr->Instruction->U.P,
+                                               &list_ptr->Instruction->U.P)) {
+                                       remove_inst_from_list(&s->ReadyAlpha, list_ptr);
+                                       remove_inst_from_list(&s->ReadyRGB, pair_ptr);
+                                       pair_ptr->PairedInst = list_ptr;
+
+                                       add_inst_to_list(&s->ReadyFullALU, pair_ptr);
+                                       list_ptr = *inst_list;
+                                       paired = 1;
+                                       break;
+                               }
+
+                       }
+               }
+               if (!paired) {
+next:
+                       list_ptr = list_ptr->NextReady;
+               }
+       }
+}
+
 /**
  * This function attempts to merge RGB and Alpha instructions together.
  */
@@ -969,38 +1018,13 @@ static void pair_instructions(struct schedule_state * s)
                return;
        }
 
+       /* Full instructions that have RC_OPCODE_REPL_ALPHA in the RGB
+        * slot can be converted into Alpha instructions. */
+       try_convert_and_pair(s, &s->ReadyFullALU);
+
        /* 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;
-                       remove_inst_from_list(&s->ReadyRGB, rgb_ptr);
-                       add_inst_to_list_score(&s->ReadyAlpha, rgb_ptr);
-
-                       for (pair_ptr = s->ReadyRGB; pair_ptr;
-                                       pair_ptr = pair_ptr->NextReady) {
-                               if (merge_instructions(&pair_ptr->Instruction->U.P,
-                                               &rgb_ptr->Instruction->U.P)) {
-                                       remove_inst_from_list(&s->ReadyAlpha, 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;
-               }
-       }
+       try_convert_and_pair(s, &s->ReadyRGB);
 }
 
 static void update_max_score(