Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2011 Tom Stellard <tstellar@gmail.com>
  3.  *
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining
  7.  * a copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sublicense, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial
  16.  * portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  21.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  22.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  */
  27.  
  28. #include "radeon_variable.h"
  29.  
  30. #include "memory_pool.h"
  31. #include "radeon_compiler_util.h"
  32. #include "radeon_dataflow.h"
  33. #include "radeon_list.h"
  34. #include "radeon_opcodes.h"
  35. #include "radeon_program.h"
  36.  
  37. /**
  38.  * Rewrite the index and writemask for the destination register of var
  39.  * and its friends to new_index and new_writemask.  This function also takes
  40.  * care of rewriting the swizzles for the sources of var.
  41.  */
  42. void rc_variable_change_dst(
  43.         struct rc_variable * var,
  44.         unsigned int new_index,
  45.         unsigned int new_writemask)
  46. {
  47.         struct rc_variable * var_ptr;
  48.         struct rc_list * readers;
  49.         unsigned int old_mask = rc_variable_writemask_sum(var);
  50.         unsigned int conversion_swizzle =
  51.                         rc_make_conversion_swizzle(old_mask, new_writemask);
  52.  
  53.         for (var_ptr = var; var_ptr; var_ptr = var_ptr->Friend) {
  54.                 if (var_ptr->Inst->Type == RC_INSTRUCTION_NORMAL) {
  55.                         rc_normal_rewrite_writemask(var_ptr->Inst,
  56.                                                         conversion_swizzle);
  57.                         var_ptr->Inst->U.I.DstReg.Index = new_index;
  58.                 } else {
  59.                         struct rc_pair_sub_instruction * sub;
  60.                         if (var_ptr->Dst.WriteMask == RC_MASK_W) {
  61.                                 assert(new_writemask & RC_MASK_W);
  62.                                 sub = &var_ptr->Inst->U.P.Alpha;
  63.                         } else {
  64.                                 sub = &var_ptr->Inst->U.P.RGB;
  65.                                 rc_pair_rewrite_writemask(sub,
  66.                                                         conversion_swizzle);
  67.                         }
  68.                         sub->DestIndex = new_index;
  69.                 }
  70.         }
  71.  
  72.         readers = rc_variable_readers_union(var);
  73.  
  74.         for ( ; readers; readers = readers->Next) {
  75.                 struct rc_reader * reader = readers->Item;
  76.                 if (reader->Inst->Type == RC_INSTRUCTION_NORMAL) {
  77.                         reader->U.I.Src->Index = new_index;
  78.                         reader->U.I.Src->Swizzle = rc_rewrite_swizzle(
  79.                                 reader->U.I.Src->Swizzle, conversion_swizzle);
  80.                 } else {
  81.                         struct rc_pair_instruction * pair_inst =
  82.                                                         &reader->Inst->U.P;
  83.                         unsigned int src_type = rc_source_type_swz(
  84.                                                         reader->U.P.Arg->Swizzle);
  85.  
  86.                         int src_index = reader->U.P.Arg->Source;
  87.                         if (src_index == RC_PAIR_PRESUB_SRC) {
  88.                                 src_index = rc_pair_get_src_index(
  89.                                                 pair_inst, reader->U.P.Src);
  90.                         }
  91.                         /* Try to delete the old src, it is OK if this fails,
  92.                          * because rc_pair_alloc_source might be able to
  93.                          * find a source the ca be reused.
  94.                          */
  95.                         if (rc_pair_remove_src(reader->Inst, src_type,
  96.                                                         src_index, old_mask)) {
  97.                                 /* Reuse the source index of the source that
  98.                                  * was just deleted and set its register
  99.                                  * index.  We can't use rc_pair_alloc_source
  100.                                  * for this becuase it might return a source
  101.                                  * index that is already being used. */
  102.                                 if (src_type & RC_SOURCE_RGB) {
  103.                                         pair_inst->RGB.Src[src_index]
  104.                                                 .Used = 1;
  105.                                         pair_inst->RGB.Src[src_index]
  106.                                                 .Index = new_index;
  107.                                         pair_inst->RGB.Src[src_index]
  108.                                                 .File = RC_FILE_TEMPORARY;
  109.                                 }
  110.                                 if (src_type & RC_SOURCE_ALPHA) {
  111.                                         pair_inst->Alpha.Src[src_index]
  112.                                                 .Used = 1;
  113.                                         pair_inst->Alpha.Src[src_index]
  114.                                                 .Index = new_index;
  115.                                         pair_inst->Alpha.Src[src_index]
  116.                                                 .File = RC_FILE_TEMPORARY;
  117.                                 }
  118.                         } else {
  119.                                 src_index = rc_pair_alloc_source(
  120.                                                 &reader->Inst->U.P,
  121.                                                 src_type & RC_SOURCE_RGB,
  122.                                                 src_type & RC_SOURCE_ALPHA,
  123.                                                 RC_FILE_TEMPORARY,
  124.                                                 new_index);
  125.                                 if (src_index < 0) {
  126.                                         rc_error(var->C, "Rewrite of inst %u failed "
  127.                                                 "Can't allocate source for "
  128.                                                 "Inst %u src_type=%x "
  129.                                                 "new_index=%u new_mask=%u\n",
  130.                                                 var->Inst->IP, reader->Inst->IP, src_type, new_index, new_writemask);
  131.                                                 continue;
  132.                                 }
  133.                         }
  134.                         reader->U.P.Arg->Swizzle = rc_rewrite_swizzle(
  135.                                 reader->U.P.Arg->Swizzle, conversion_swizzle);
  136.                         if (reader->U.P.Arg->Source != RC_PAIR_PRESUB_SRC) {
  137.                                 reader->U.P.Arg->Source = src_index;
  138.                         }
  139.                 }
  140.         }
  141. }
  142.  
  143. /**
  144.  * Compute the live intervals for var and its friends.
  145.  */
  146. void rc_variable_compute_live_intervals(struct rc_variable * var)
  147. {
  148.         while(var) {
  149.                 unsigned int i;
  150.                 unsigned int start = var->Inst->IP;
  151.  
  152.                 for (i = 0; i < var->ReaderCount; i++) {
  153.                         unsigned int chan;
  154.                         unsigned int chan_start = start;
  155.                         unsigned int chan_end = var->Readers[i].Inst->IP;
  156.                         unsigned int mask = var->Readers[i].WriteMask;
  157.                         struct rc_instruction * inst;
  158.  
  159.                         /* Extend the live interval of T0 to the start of the
  160.                          * loop for sequences like:
  161.                          * BGNLOOP
  162.                          * read T0
  163.                          * ...
  164.                          * write T0
  165.                          * ENDLOOP
  166.                          */
  167.                         if (var->Readers[i].Inst->IP < start) {
  168.                                 struct rc_instruction * bgnloop =
  169.                                         rc_match_endloop(var->Readers[i].Inst);
  170.                                 chan_start = bgnloop->IP;
  171.                         }
  172.  
  173.                         /* Extend the live interval of T0 to the start of the
  174.                          * loop in case there is a BRK instruction in the loop
  175.                          * (we don't actually check for a BRK instruction we
  176.                          * assume there is one somewhere in the loop, which
  177.                          * there usually is) for sequences like:
  178.                          * BGNLOOP
  179.                          * ...
  180.                          * conditional BRK
  181.                          * ...
  182.                          * write T0
  183.                          * ENDLOOP
  184.                          * read T0
  185.                          ***************************************************
  186.                          * Extend the live interval of T0 to the end of the
  187.                          * loop for sequences like:
  188.                          * write T0
  189.                          * BGNLOOP
  190.                          * ...
  191.                          * read T0
  192.                          * ENDLOOP
  193.                          */
  194.                         for (inst = var->Inst; inst != var->Readers[i].Inst;
  195.                                                         inst = inst->Next) {
  196.                                 rc_opcode op = rc_get_flow_control_inst(inst);
  197.                                 if (op == RC_OPCODE_ENDLOOP) {
  198.                                         struct rc_instruction * bgnloop =
  199.                                                 rc_match_endloop(inst);
  200.                                         if (bgnloop->IP < chan_start) {
  201.                                                 chan_start = bgnloop->IP;
  202.                                         }
  203.                                 } else if (op == RC_OPCODE_BGNLOOP) {
  204.                                         struct rc_instruction * endloop =
  205.                                                 rc_match_bgnloop(inst);
  206.                                         if (endloop->IP > chan_end) {
  207.                                                 chan_end = endloop->IP;
  208.                                         }
  209.                                 }
  210.                         }
  211.  
  212.                         for (chan = 0; chan < 4; chan++) {
  213.                                 if ((mask >> chan) & 0x1) {
  214.                                         if (!var->Live[chan].Used
  215.                                         || chan_start < var->Live[chan].Start) {
  216.                                                 var->Live[chan].Start =
  217.                                                                 chan_start;
  218.                                         }
  219.                                         if (!var->Live[chan].Used
  220.                                         || chan_end > var->Live[chan].End) {
  221.                                                 var->Live[chan].End = chan_end;
  222.                                         }
  223.                                         var->Live[chan].Used = 1;
  224.                                 }
  225.                         }
  226.                 }
  227.                 var = var->Friend;
  228.         }
  229. }
  230.  
  231. /**
  232.  * @return 1 if a and b share a reader
  233.  * @return 0 if they do not
  234.  */
  235. static unsigned int readers_intersect(
  236.         struct rc_variable * a,
  237.         struct rc_variable * b)
  238. {
  239.         unsigned int a_index, b_index;
  240.         for (a_index = 0; a_index < a->ReaderCount; a_index++) {
  241.                 struct rc_reader reader_a = a->Readers[a_index];
  242.                 for (b_index = 0; b_index < b->ReaderCount; b_index++) {
  243.                         struct rc_reader reader_b = b->Readers[b_index];
  244.                         if (reader_a.Inst->Type == RC_INSTRUCTION_NORMAL
  245.                                 && reader_b.Inst->Type == RC_INSTRUCTION_NORMAL
  246.                                 && reader_a.U.I.Src == reader_b.U.I.Src) {
  247.  
  248.                                 return 1;
  249.                         }
  250.                         if (reader_a.Inst->Type == RC_INSTRUCTION_PAIR
  251.                                 && reader_b.Inst->Type == RC_INSTRUCTION_PAIR
  252.                                 && reader_a.U.P.Src == reader_b.U.P.Src) {
  253.  
  254.                                 return 1;
  255.                         }
  256.                 }
  257.         }
  258.         return 0;
  259. }
  260.  
  261. void rc_variable_add_friend(
  262.         struct rc_variable * var,
  263.         struct rc_variable * friend)
  264. {
  265.         assert(var->Dst.Index == friend->Dst.Index);
  266.         while(var->Friend) {
  267.                 var = var->Friend;
  268.         }
  269.         var->Friend = friend;
  270. }
  271.  
  272. struct rc_variable * rc_variable(
  273.         struct radeon_compiler * c,
  274.         unsigned int DstFile,
  275.         unsigned int DstIndex,
  276.         unsigned int DstWriteMask,
  277.         struct rc_reader_data * reader_data)
  278. {
  279.         struct rc_variable * new =
  280.                         memory_pool_malloc(&c->Pool, sizeof(struct rc_variable));
  281.         memset(new, 0, sizeof(struct rc_variable));
  282.         new->C = c;
  283.         new->Dst.File = DstFile;
  284.         new->Dst.Index = DstIndex;
  285.         new->Dst.WriteMask = DstWriteMask;
  286.         if (reader_data) {
  287.                 new->Inst = reader_data->Writer;
  288.                 new->ReaderCount = reader_data->ReaderCount;
  289.                 new->Readers = reader_data->Readers;
  290.         }
  291.         return new;
  292. }
  293.  
  294. static void get_variable_helper(
  295.         struct rc_list ** variable_list,
  296.         struct rc_variable * variable)
  297. {
  298.         struct rc_list * list_ptr;
  299.         for (list_ptr = *variable_list; list_ptr; list_ptr = list_ptr->Next) {
  300.                 struct rc_variable * var;
  301.                 for (var = list_ptr->Item; var; var = var->Friend) {
  302.                         if (readers_intersect(var, variable)) {
  303.                                 rc_variable_add_friend(var, variable);
  304.                                 return;
  305.                         }
  306.                 }
  307.         }
  308.         rc_list_add(variable_list, rc_list(&variable->C->Pool, variable));
  309. }
  310.  
  311. static void get_variable_pair_helper(
  312.         struct rc_list ** variable_list,
  313.         struct radeon_compiler * c,
  314.         struct rc_instruction * inst,
  315.         struct rc_pair_sub_instruction * sub_inst)
  316. {
  317.         struct rc_reader_data reader_data;
  318.         struct rc_variable * new_var;
  319.         rc_register_file file;
  320.         unsigned int writemask;
  321.  
  322.         if (sub_inst->Opcode == RC_OPCODE_NOP) {
  323.                 return;
  324.         }
  325.         memset(&reader_data, 0, sizeof(struct rc_reader_data));
  326.         rc_get_readers_sub(c, inst, sub_inst, &reader_data, NULL, NULL, NULL);
  327.  
  328.         if (reader_data.ReaderCount == 0) {
  329.                 return;
  330.         }
  331.  
  332.         if (sub_inst->WriteMask) {
  333.                 file = RC_FILE_TEMPORARY;
  334.                 writemask = sub_inst->WriteMask;
  335.         } else if (sub_inst->OutputWriteMask) {
  336.                 file = RC_FILE_OUTPUT;
  337.                 writemask = sub_inst->OutputWriteMask;
  338.         } else {
  339.                 writemask = 0;
  340.                 file = RC_FILE_NONE;
  341.         }
  342.         new_var = rc_variable(c, file, sub_inst->DestIndex, writemask,
  343.                                                                 &reader_data);
  344.         get_variable_helper(variable_list, new_var);
  345. }
  346.  
  347. /**
  348.  * Generate a list of variables used by the shader program.  Each instruction
  349.  * that writes to a register is considered a variable.  The struct rc_variable
  350.  * data structure includes a list of readers and is essentially a
  351.  * definition-use chain.  Any two variables that share a reader are considered
  352.  * "friends" and they are linked together via the Friend attribute.
  353.  */
  354. struct rc_list * rc_get_variables(struct radeon_compiler * c)
  355. {
  356.         struct rc_instruction * inst;
  357.         struct rc_list * variable_list = NULL;
  358.  
  359.         for (inst = c->Program.Instructions.Next;
  360.                                         inst != &c->Program.Instructions;
  361.                                         inst = inst->Next) {
  362.                 struct rc_reader_data reader_data;
  363.                 struct rc_variable * new_var;
  364.                 memset(&reader_data, 0, sizeof(reader_data));
  365.  
  366.                 if (inst->Type == RC_INSTRUCTION_NORMAL) {
  367.                         rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL);
  368.                         if (reader_data.ReaderCount == 0) {
  369.                                 continue;
  370.                         }
  371.                         new_var = rc_variable(c, inst->U.I.DstReg.File,
  372.                                 inst->U.I.DstReg.Index,
  373.                                 inst->U.I.DstReg.WriteMask, &reader_data);
  374.                         get_variable_helper(&variable_list, new_var);
  375.                 } else {
  376.                         get_variable_pair_helper(&variable_list, c, inst,
  377.                                                         &inst->U.P.RGB);
  378.                         get_variable_pair_helper(&variable_list, c, inst,
  379.                                                         &inst->U.P.Alpha);
  380.                 }
  381.         }
  382.  
  383.         return variable_list;
  384. }
  385.  
  386. /**
  387.  * @return The bitwise or of the writemasks of a variable and all of its
  388.  * friends.
  389.  */
  390. unsigned int rc_variable_writemask_sum(struct rc_variable * var)
  391. {
  392.         unsigned int writemask = 0;
  393.         while(var) {
  394.                 writemask |= var->Dst.WriteMask;
  395.                 var = var->Friend;
  396.         }
  397.         return writemask;
  398. }
  399.  
  400. /*
  401.  * @return A list of readers for a variable and its friends.  Readers
  402.  * that read from two different variable friends are only included once in
  403.  * this list.
  404.  */
  405. struct rc_list * rc_variable_readers_union(struct rc_variable * var)
  406. {
  407.         struct rc_list * list = NULL;
  408.         while (var) {
  409.                 unsigned int i;
  410.                 for (i = 0; i < var->ReaderCount; i++) {
  411.                         struct rc_list * temp;
  412.                         struct rc_reader * a = &var->Readers[i];
  413.                         unsigned int match = 0;
  414.                         for (temp = list; temp; temp = temp->Next) {
  415.                                 struct rc_reader * b = temp->Item;
  416.                                 if (a->Inst->Type != b->Inst->Type) {
  417.                                         continue;
  418.                                 }
  419.                                 if (a->Inst->Type == RC_INSTRUCTION_NORMAL) {
  420.                                         if (a->U.I.Src == b->U.I.Src) {
  421.                                                 match = 1;
  422.                                                 break;
  423.                                         }
  424.                                 }
  425.                                 if (a->Inst->Type == RC_INSTRUCTION_PAIR) {
  426.                                         if (a->U.P.Arg == b->U.P.Arg
  427.                                             && a->U.P.Src == b->U.P.Src) {
  428.                                                 match = 1;
  429.                                                 break;
  430.                                         }
  431.                                 }
  432.                         }
  433.                         if (match) {
  434.                                 continue;
  435.                         }
  436.                         rc_list_add(&list, rc_list(&var->C->Pool, a));
  437.                 }
  438.                 var = var->Friend;
  439.         }
  440.         return list;
  441. }
  442.  
  443. static unsigned int reader_equals_src(
  444.         struct rc_reader reader,
  445.         unsigned int src_type,
  446.         void * src)
  447. {
  448.         if (reader.Inst->Type != src_type) {
  449.                 return 0;
  450.         }
  451.         if (src_type == RC_INSTRUCTION_NORMAL) {
  452.                 return reader.U.I.Src == src;
  453.         } else {
  454.                 return reader.U.P.Src == src;
  455.         }
  456. }
  457.  
  458. static unsigned int variable_writes_src(
  459.         struct rc_variable * var,
  460.         unsigned int src_type,
  461.         void * src)
  462. {
  463.         unsigned int i;
  464.         for (i = 0; i < var->ReaderCount; i++) {
  465.                 if (reader_equals_src(var->Readers[i], src_type, src)) {
  466.                         return 1;
  467.                 }
  468.         }
  469.         return 0;
  470. }
  471.  
  472.  
  473. struct rc_list * rc_variable_list_get_writers(
  474.         struct rc_list * var_list,
  475.         unsigned int src_type,
  476.         void * src)
  477. {
  478.         struct rc_list * list_ptr;
  479.         struct rc_list * writer_list = NULL;
  480.         for (list_ptr = var_list; list_ptr; list_ptr = list_ptr->Next) {
  481.                 struct rc_variable * var = list_ptr->Item;
  482.                 if (variable_writes_src(var, src_type, src)) {
  483.                         struct rc_variable * friend;
  484.                         rc_list_add(&writer_list, rc_list(&var->C->Pool, var));
  485.                         for (friend = var->Friend; friend;
  486.                                                 friend = friend->Friend) {
  487.                                 if (variable_writes_src(friend, src_type, src)) {
  488.                                         rc_list_add(&writer_list,
  489.                                                 rc_list(&var->C->Pool, friend));
  490.                                 }
  491.                         }
  492.                         /* Once we have indentifed the variable and its
  493.                          * friends that write this source, we can stop
  494.                          * stop searching, because we know none of the
  495.                          * other variables in the list will write this source.
  496.                          * If they did they would be friends of var.
  497.                          */
  498.                         break;
  499.                 }
  500.         }
  501.         return writer_list;
  502. }
  503.  
  504. struct rc_list * rc_variable_list_get_writers_one_reader(
  505.         struct rc_list * var_list,
  506.         unsigned int src_type,
  507.         void * src)
  508. {
  509.         struct rc_list * writer_list =
  510.                 rc_variable_list_get_writers(var_list, src_type, src);
  511.         struct rc_list * reader_list =
  512.                 rc_variable_readers_union(writer_list->Item);
  513.         if (rc_list_count(reader_list) > 1) {
  514.                 return NULL;
  515.         } else {
  516.                 return writer_list;
  517.         }
  518. }
  519.  
  520. void rc_variable_print(struct rc_variable * var)
  521. {
  522.         unsigned int i;
  523.         while (var) {
  524.                 fprintf(stderr, "%u: TEMP[%u].%u: ",
  525.                         var->Inst->IP, var->Dst.Index, var->Dst.WriteMask);
  526.                 for (i = 0; i < 4; i++) {
  527.                         fprintf(stderr, "chan %u: start=%u end=%u ", i,
  528.                                         var->Live[i].Start, var->Live[i].End);
  529.                 }
  530.                 fprintf(stderr, "%u readers\n", var->ReaderCount);
  531.                 if (var->Friend) {
  532.                         fprintf(stderr, "Friend: \n\t");
  533.                 }
  534.                 var = var->Friend;
  535.         }
  536. }
  537.