On 31 August 2012 11:32, Eric Anholt <span dir="ltr"><<a href="mailto:eric@anholt.net" target="_blank">eric@anholt.net</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
 src/mesa/drivers/dri/i965/brw_eu_compact.c |  111 ++++++++++++++++++++++------<br>
 1 file changed, 87 insertions(+), 24 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_eu_compact.c b/src/mesa/drivers/dri/i965/brw_eu_compact.c<br>
index 2c15c85..dd661f5 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_eu_compact.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_eu_compact.c<br>
@@ -324,6 +324,19 @@ brw_try_compact_instruction(struct brw_compile *c,<br>
       return false; /* FINISHME: What else needs handling? */<br>
    }<br>
<br>
+<br>
+   if (src->header.opcode == BRW_OPCODE_IF ||<br>
+       src->header.opcode == BRW_OPCODE_ELSE ||<br>
+       src->header.opcode == BRW_OPCODE_ENDIF ||<br>
+       src->header.opcode == BRW_OPCODE_DO ||<br>
+       src->header.opcode == BRW_OPCODE_HALT ||<br>
+       src->header.opcode == BRW_OPCODE_WHILE) {<br>
+      /* FINISHME: The fixup code below, and brw_set_uip_jip and friends, needs<br>
+       * to be able to handle flow control.<br>
+       */<br>
+      return false;<br>
+   }<br>
+<br>
    /* FINISHME: immediates */<br>
    if (src->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE ||<br>
        src->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE)<br>
@@ -476,12 +489,40 @@ void brw_debug_compact_uncompact(struct intel_context *intel,<br>
    }<br>
 }<br>
<br>
+static int<br>
+compressed_between(int old_ip, int old_target_ip, int *compressed_counts)<br>
+{<br>
+   int this_compressed_count = compressed_counts[old_ip];<br>
+   int target_compressed_count = compressed_counts[old_target_ip];<br>
+   return target_compressed_count - this_compressed_count;<br>
+}<br>
+<br>
+static void<br>
+update_uip_jip(struct brw_instruction *insn, int this_old_ip,<br>
+              int *compressed_counts)<br>
+{<br>
+   int target_old_ip;<br>
+<br>
+   target_old_ip = this_old_ip + insn->bits3.break_cont.jip;<br>
+   insn->bits3.break_cont.jip -= compressed_between(this_old_ip,<br>
+                                                   target_old_ip,<br>
+                                                   compressed_counts);<br>
+<br>
+   target_old_ip = this_old_ip + insn->bits3.break_cont.uip;<br>
+   insn->bits3.break_cont.uip -= compressed_between(this_old_ip,<br>
+                                                   target_old_ip,<br>
+                                                   compressed_counts);<br>
+}<br>
+<br>
 void<br>
 brw_compact_instructions(struct brw_compile *p)<br>
 {<br>
    struct brw_context *brw = p->brw;<br>
    struct intel_context *intel = &brw->intel;<br>
    void *store = p->store;<br>
+   /* Control flow fixup information */<br>
+   int compressed_counts[p->next_insn_offset / 8];<br></blockquote><div><br>A comment would have saved me some time in understanding what information is stored in compressed_counts.  I think this would be a correct description but I'm not certain: "If an instruction was located at offset 8*i before compaction, compressed_counts[i] is the number of instructions that preceded it which were not previously compressed, but are now."<br>
<br>An alternative way of representing the same information, possibly easier to follow, would be:<br><br>/* If an instruction was located at offset 8*i before compaction, 8*new_ip[i] is the location of the instruction after compaction */<br>
int new_ip[p->next_insn_offset / 8];<br><br>(Of course, update_uip_jip() would need to be reworked)<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   int old_ip[p->next_insn_offset / 8];<br></blockquote><div><br>And, assuming I'm understanding the code correctly, I believe old_ip could be commented:<br><br>/* If an instruction is located at offset 8*i after compaction, 8*old_ip[i] was the location of the instruction before compaction.  In the case of NOPs inserted automatically for alignment, 8*old_ip[i] was the old location of the instruction that needed to be aligned. */<br>
 <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
    assert(gen6_control_index_table[ARRAY_SIZE(gen6_control_index_table) - 1] != 0);<br>
    assert(gen6_datatype_table[ARRAY_SIZE(gen6_datatype_table) - 1] != 0);<br>
@@ -491,36 +532,21 @@ brw_compact_instructions(struct brw_compile *p)<br>
    if (intel->gen != 6)<br>
       return;<br>
<br>
-   /* FINISHME: If we are going to compress instructions between flow control,<br>
-    * we have to do fixups to flow control offsets to represent the new<br>
-    * distances, since flow control uses (virtual address distance)/2, not a<br>
-    * logical instruction count.<br>
-    */<br>
-   bool continue_compressing = true;<br>
-   for (int i = 0; i < p->nr_insn; i++) {<br>
-      if (p->store[i].header.opcode == BRW_OPCODE_WHILE)<br>
-        return;<br>
-   }<br>
-<br>
    int src_offset;<br>
    int offset = 0;<br>
+   int compressed_count = 0;<br>
    for (src_offset = 0; src_offset < p->nr_insn * 16;) {<br>
       struct brw_instruction *src = store + src_offset;<br>
       void *dst = store + offset;<br>
<br>
-      switch (src->header.opcode) {<br>
-      case BRW_OPCODE_IF:<br>
-      case BRW_OPCODE_HALT:<br>
-      case BRW_OPCODE_JMPI:<br>
-        continue_compressing = false;<br>
-        break;<br>
-      }<br>
+      old_ip[offset / 8] = src_offset / 8;<br>
+      compressed_counts[src_offset / 8] = compressed_count;<br>
<br>
       struct brw_instruction saved = *src;<br>
<br>
-      if (continue_compressing &&<br>
-         !src->header.cmpt_control &&<br>
+      if (!src->header.cmpt_control &&<br>
          brw_try_compact_instruction(p, dst, src)) {<br>
+        compressed_count++;<br>
<br>
         /* debug */<br>
         struct brw_instruction uncompacted;<br>
@@ -544,6 +570,7 @@ brw_compact_instructions(struct brw_compile *p)<br>
            align->dw0.opcode = BRW_OPCODE_NOP;<br>
            align->dw0.cmpt_ctrl = 1;<br>
            offset += 8;<br>
+           old_ip[offset / 8] = src_offset / 8;<br>
            dst = store + offset;<br>
         }<br>
<br>
@@ -558,20 +585,56 @@ brw_compact_instructions(struct brw_compile *p)<br>
       }<br>
    }<br></blockquote><div><br>I'm running out of time to look at this today, so I had to stop reviewing here.  I think the stuff that follows is likely correct (because if it weren't, it would probably fail spectacularly :)).  I'll try to return to it tomorrow just to make sure.<br>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
+   /* Fix up control flow offsets. */<br>
+   p->next_insn_offset = offset;<br>
+   for (offset = 0; offset < p->next_insn_offset;) {<br>
+      struct brw_instruction *insn = store + offset;<br>
+      int this_old_ip = old_ip[offset / 8];<br>
+      int this_compressed_count = compressed_counts[this_old_ip];<br>
+      int target_old_ip, target_compressed_count;<br>
+<br>
+      switch (insn->header.opcode) {<br>
+      case BRW_OPCODE_BREAK:<br>
+      case BRW_OPCODE_CONTINUE:<br>
+      case BRW_OPCODE_HALT:<br>
+        update_uip_jip(insn, this_old_ip, compressed_counts);<br>
+        break;<br>
+<br>
+      case BRW_OPCODE_IF:<br>
+      case BRW_OPCODE_ELSE:<br>
+      case BRW_OPCODE_ENDIF:<br>
+      case BRW_OPCODE_WHILE:<br>
+        if (intel->gen == 6) {<br>
+           target_old_ip = this_old_ip + insn->bits1.branch_gen6.jump_count;<br>
+           target_compressed_count = compressed_counts[target_old_ip];<br>
+           insn->bits1.branch_gen6.jump_count -= (target_compressed_count -<br>
+                                                  this_compressed_count);<br>
+        } else {<br>
+           update_uip_jip(insn, this_old_ip, compressed_counts);<br>
+        }<br>
+        break;<br>
+      }<br>
+<br>
+      if (insn->header.cmpt_control) {<br>
+        offset += 8;<br>
+      } else {<br>
+        offset += 16;<br>
+      }<br>
+   }<br>
+<br>
    /* p->nr_insn is counting the number of uncompacted instructions still, so<br>
     * divide.  We do want to be sure there's a valid instruction in any<br>
     * alignment padding, so that the next compression pass (for the FS 8/16<br>
     * compile passes) parses correctly.<br>
     */<br>
-   if (offset & 8) {<br>
+   if (p->next_insn_offset & 8) {<br>
       struct brw_compact_instruction *align = store + offset;<br>
       memset(align, 0, sizeof(*align));<br>
       align->dw0.opcode = BRW_OPCODE_NOP;<br>
       align->dw0.cmpt_ctrl = 1;<br>
-      offset += 8;<br>
+      p->next_insn_offset += 8;<br>
    }<br>
-   p->next_insn_offset = offset;<br>
-   p->nr_insn = offset / 16;<br>
+   p->nr_insn = p->next_insn_offset / 16;<br>
<br>
    if (0) {<br>
       fprintf(stdout, "dumping compacted program\n");<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.10.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br>