r300/compiler: Create a helper function for merging presubtract sources
authorTom Stellard <tstellar@gmail.com>
Fri, 1 Oct 2010 06:36:57 +0000 (23:36 -0700)
committerTom Stellard <tstellar@gmail.com>
Tue, 19 Oct 2010 03:51:05 +0000 (20:51 -0700)
src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c

index bfe3553..15e7c0b 100644 (file)
@@ -275,13 +275,112 @@ static void emit_all_tex(struct schedule_state * s, struct rc_instruction * befo
        }
 }
 
+/* This is a helper function for destructive_merge_instructions().  It helps
+ * merge presubtract sources from two instructions and makes sure the
+ * presubtract sources end up in the correct spot.  This function assumes that
+ * dst_full is an rgb instruction, meaning that it has a vector instruction(rgb)
+ * but no scalar instruction (alpha).
+ * @return 0 if merging the presubtract sources fails.
+ * @retrun 1 if merging the presubtract sources succeeds.
+ */
+static int merge_presub_sources(
+       struct rc_pair_instruction * dst_full,
+       struct rc_pair_sub_instruction src,
+       rc_pair_source_type type)
+{
+       unsigned int srcp_src, srcp_regs, is_rgb, is_alpha;
+       struct rc_pair_sub_instruction * dst_sub;
+
+       assert(dst_full->Alpha.Opcode == RC_OPCODE_NOP);
+
+       switch(type) {
+       case RC_PAIR_SOURCE_RGB:
+               is_rgb = 1;
+               is_alpha = 0;
+               dst_sub = &dst_full->RGB;
+               break;
+       case RC_PAIR_SOURCE_ALPHA:
+               is_rgb = 0;
+               is_alpha = 1;
+               dst_sub = &dst_full->Alpha;
+               break;
+       default:
+               assert(0);
+               return 0;
+       }
+
+       const struct rc_opcode_info * info =
+                                       rc_get_opcode_info(dst_full->RGB.Opcode);
+       if (dst_sub->Src[RC_PAIR_PRESUB_SRC].Used)
+               return 0;
+
+       srcp_regs = rc_presubtract_src_reg_count(
+                                       src.Src[RC_PAIR_PRESUB_SRC].Index);
+       for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) {
+               unsigned int arg;
+               int free_source;
+               unsigned int one_way = 0;
+               struct rc_pair_instruction_source srcp = src.Src[srcp_src];
+               struct rc_pair_instruction_source temp;
+
+               free_source = rc_pair_alloc_source(dst_full, is_rgb, is_alpha,
+                                                       srcp.File, srcp.Index);
+
+               /* If free_source < 0 then there are no free source
+                * slots. */
+               if (free_source < 0)
+                       return 0;
+
+               temp = dst_sub->Src[srcp_src];
+               dst_sub->Src[srcp_src] = dst_sub->Src[free_source];
+
+               /* srcp needs src0 and src1 to be the same */
+               if (free_source < srcp_src) {
+                       if (!temp.Used)
+                               continue;
+                       free_source = rc_pair_alloc_source(dst_full, is_rgb,
+                                       is_alpha, temp.File, temp.Index);
+                       one_way = 1;
+               } else {
+                       dst_sub->Src[free_source] = temp;
+               }
+
+               /* If free_source == srcp_src, then the presubtract
+                * source is already in the correct place. */
+               if (free_source == srcp_src)
+                       continue;
+
+               /* Shuffle the sources, so we can put the
+                * presubtract source in the correct place. */
+               for(arg = 0; arg < info->NumSrcRegs; arg++) {
+                       /*If this arg does not read from an rgb source,
+                        * do nothing. */
+                       if (rc_source_type_that_arg_reads(
+                               dst_full->RGB.Arg[arg].Source,
+                               dst_full->RGB.Arg[arg].Swizzle, 3) != type) {
+                               continue;
+                       }
+                       if (dst_full->RGB.Arg[arg].Source == srcp_src)
+                               dst_full->RGB.Arg[arg].Source = free_source;
+                       /* We need to do this just in case register
+                        * is one of the sources already, but in the
+                        * wrong spot. */
+                       else if(dst_full->RGB.Arg[arg].Source == free_source
+                                                       && !one_way) {
+                               dst_full->RGB.Arg[arg].Source = srcp_src;
+                       }
+               }
+       }
+       return 1;
+}
+
 
+/* This function assumes that rgb.Alpha and alpha.RGB are unused */
 static int destructive_merge_instructions(
                struct rc_pair_instruction * rgb,
                struct rc_pair_instruction * alpha)
 {
        const struct rc_opcode_info * opcode;
-       const struct rc_opcode_info * rgb_info;
 
        assert(rgb->Alpha.Opcode == RC_OPCODE_NOP);
        assert(alpha->RGB.Opcode == RC_OPCODE_NOP);
@@ -291,129 +390,15 @@ static int destructive_merge_instructions(
         * src1. */
 
        /* Merge the rgb presubtract registers. */
-       rgb_info = rc_get_opcode_info(rgb->RGB.Opcode);
        if (alpha->RGB.Src[RC_PAIR_PRESUB_SRC].Used) {
-               unsigned int srcp_src;
-               unsigned int srcp_regs;
-               if (rgb->RGB.Src[RC_PAIR_PRESUB_SRC].Used)
+               if (!merge_presub_sources(rgb, alpha->RGB, RC_PAIR_SOURCE_RGB)) {
                        return 0;
-               srcp_regs = rc_presubtract_src_reg_count(
-                               alpha->RGB.Src[RC_PAIR_PRESUB_SRC].Index);
-               for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) {
-                       unsigned int arg;
-                       int free_source;
-                       unsigned int one_way = 0;
-                       struct rc_pair_instruction_source srcp =
-                                               alpha->RGB.Src[srcp_src];
-                       struct rc_pair_instruction_source temp;
-                       /* 2nd arg of 1 means this is an rgb source.
-                        * 3rd arg of 0 means this is not an alpha source. */
-                       free_source = rc_pair_alloc_source(rgb, 1, 0,
-                                                       srcp.File, srcp.Index);
-                       /* If free_source < 0 then there are no free source
-                        * slots. */
-                       if (free_source < 0)
-                               return 0;
-
-                       temp = rgb->RGB.Src[srcp_src];
-                       rgb->RGB.Src[srcp_src] = rgb->RGB.Src[free_source];
-                       /* srcp needs src0 and src1 to be the same */
-                       if (free_source < srcp_src) {
-                               if (!temp.Used)
-                                       continue;
-                               free_source = rc_pair_alloc_source(rgb, 1, 0,
-                                                       srcp.File, srcp.Index);
-                               one_way = 1;
-                       } else {
-                               rgb->RGB.Src[free_source] = temp;
-                       }
-                       /* If free_source == srcp_src, then the presubtract
-                        * source is already in the correct place. */
-                       if (free_source == srcp_src)
-                               continue;
-                       /* Shuffle the sources, so we can put the
-                        * presubtract source in the correct place. */
-                       for (arg = 0; arg < rgb_info->NumSrcRegs; arg++) {
-                               /*If this arg does not read from an rgb source,
-                                * do nothing. */
-                               if (rc_source_type_that_arg_reads(
-                                       rgb->RGB.Arg[arg].Source,
-                                       rgb->RGB.Arg[arg].Swizzle, 3)
-                                                       != RC_PAIR_SOURCE_RGB) {
-                                       continue;
-                               }
-                               if (rgb->RGB.Arg[arg].Source == srcp_src)
-                                       rgb->RGB.Arg[arg].Source = free_source;
-                               /* We need to do this just in case register
-                                * is one of the sources already, but in the
-                                * wrong spot. */
-                               else if(rgb->RGB.Arg[arg].Source == free_source
-                                                               && !one_way) {
-                                       rgb->RGB.Arg[arg].Source = srcp_src;
-                               }
-                       }
                }
        }
-
        /* Merge the alpha presubtract registers */
        if (alpha->Alpha.Src[RC_PAIR_PRESUB_SRC].Used) {
-               unsigned int srcp_src;
-               unsigned int srcp_regs;
-               if(rgb->Alpha.Src[RC_PAIR_PRESUB_SRC].Used)
+               if(!merge_presub_sources(rgb,  alpha->Alpha, RC_PAIR_SOURCE_ALPHA)){
                        return 0;
-
-               srcp_regs = rc_presubtract_src_reg_count(
-                       alpha->Alpha.Src[RC_PAIR_PRESUB_SRC].Index);
-               for(srcp_src = 0; srcp_src < srcp_regs; srcp_src++) {
-                       unsigned int arg;
-                       int free_source;
-                       unsigned int one_way = 0;
-                       struct rc_pair_instruction_source srcp =
-                                               alpha->Alpha.Src[srcp_src];
-                       struct rc_pair_instruction_source temp;
-                       /* 2nd arg of 0 means this is not an rgb source.
-                        * 3rd arg of 1 means this is an alpha source. */
-                       free_source = rc_pair_alloc_source(rgb, 0, 1,
-                                                       srcp.File, srcp.Index);
-                       /* If free_source < 0 then there are no free source
-                        * slots. */
-                       if (free_source < 0)
-                               return 0;
-
-                       temp = rgb->Alpha.Src[srcp_src];
-                       rgb->Alpha.Src[srcp_src] = rgb->Alpha.Src[free_source];
-                       /* srcp needs src0 and src1 to be the same. */
-                       if (free_source < srcp_src) {
-                               if (!temp.Used)
-                                       continue;
-                               free_source = rc_pair_alloc_source(rgb, 0, 1,
-                                                       temp.File, temp.Index);
-                               one_way = 1;
-                       } else {
-                               rgb->Alpha.Src[free_source] = temp;
-                       }
-                       /* If free_source == srcp_src, then the presubtract
-                        * source is already in the correct place. */
-                       if (free_source == srcp_src)
-                               continue;
-                       /* Shuffle the sources, so we can put the
-                        * presubtract source in the correct place. */
-                       for(arg = 0; arg < rgb_info->NumSrcRegs; arg++) {
-                               /*If this arg does not read from an alpha
-                                * source, do nothing. */
-                               if (rc_source_type_that_arg_reads(
-                                       rgb->RGB.Arg[arg].Source,
-                                       rgb->RGB.Arg[arg].Swizzle, 3)
-                                               != RC_PAIR_SOURCE_ALPHA) {
-                                       continue;
-                               }
-                               if (rgb->RGB.Arg[arg].Source == srcp_src)
-                                       rgb->RGB.Arg[arg].Source = free_source;
-                               else if (rgb->RGB.Arg[arg].Source == free_source
-                                                               && !one_way) {
-                                       rgb->RGB.Arg[arg].Source = srcp_src;
-                               }
-                       }
                }
        }