i965/gs: Add a case to brwNewProgram() for geometry shaders.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_copy_propagation.cpp
index 0078c871c5d6ae3fa60230188b814b7251252352..2780ab6fd6d6663f0770a338a725377edd683ab0 100644 (file)
@@ -83,6 +83,8 @@ public:
    void setup_initial_values();
    void run();
 
+   void dump_block_data() const;
+
    void *mem_ctx;
    cfg_t *cfg;
 
@@ -132,7 +134,6 @@ fs_copy_prop_dataflow::fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg,
              */
             BITSET_SET(bd[b].copy, next_acp);
 
-            BITSET_SET(bd[b].liveout, next_acp);
             next_acp++;
          }
       }
@@ -151,6 +152,7 @@ fs_copy_prop_dataflow::fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg,
 void
 fs_copy_prop_dataflow::setup_initial_values()
 {
+   /* Initialize the COPY and KILL sets. */
    for (int b = 0; b < cfg->num_blocks; b++) {
       bblock_t *block = cfg->blocks[b];
 
@@ -169,6 +171,26 @@ fs_copy_prop_dataflow::setup_initial_values()
          }
       }
    }
+
+   /* Populate the initial values for the livein and liveout sets.  For the
+    * block at the start of the program, livein = 0 and liveout = copy.
+    * For the others, set liveout to 0 (the empty set) and livein to ~0
+    * (the universal set).
+    */
+   for (int b = 0; b < cfg->num_blocks; b++) {
+      bblock_t *block = cfg->blocks[b];
+      if (block->parents.is_empty()) {
+         for (int i = 0; i < bitset_words; i++) {
+            bd[b].livein[i] = 0u;
+            bd[b].liveout[i] = bd[b].copy[i];
+         }
+      } else {
+         for (int i = 0; i < bitset_words; i++) {
+            bd[b].liveout[i] = 0u;
+            bd[b].livein[i] = ~0u;
+         }
+      }
+   }
 }
 
 /**
@@ -185,10 +207,14 @@ fs_copy_prop_dataflow::run()
 
       /* Update liveout for all blocks. */
       for (int b = 0; b < cfg->num_blocks; b++) {
+         if (cfg->blocks[b]->parents.is_empty())
+            continue;
+
          for (int i = 0; i < bitset_words; i++) {
             const BITSET_WORD old_liveout = bd[b].liveout[i];
 
-            bd[b].liveout[i] |= bd[b].livein[i] & ~bd[b].kill[i];
+            bd[b].liveout[i] =
+               bd[b].copy[i] | (bd[b].livein[i] & ~bd[b].kill[i]);
 
             if (old_liveout != bd[b].liveout[i])
                progress = true;
@@ -199,24 +225,54 @@ fs_copy_prop_dataflow::run()
        * blocks, it's live coming in to this block.
        */
       for (int b = 0; b < cfg->num_blocks; b++) {
+         if (cfg->blocks[b]->parents.is_empty())
+            continue;
+
          for (int i = 0; i < bitset_words; i++) {
-            BITSET_WORD new_livein = ~bd[b].livein[i];
+            const BITSET_WORD old_livein = bd[b].livein[i];
+
+            bd[b].livein[i] = ~0u;
             foreach_list(block_node, &cfg->blocks[b]->parents) {
                bblock_link *link = (bblock_link *)block_node;
                bblock_t *block = link->block;
-               new_livein &= bd[block->block_num].liveout[i];
-               if (!new_livein)
-                  break;
+               bd[b].livein[i] &= bd[block->block_num].liveout[i];
             }
-            if (new_livein) {
-               bd[b].livein[i] |= new_livein;
+
+            if (old_livein != bd[b].livein[i])
                progress = true;
-            }
          }
       }
    } while (progress);
 }
 
+void
+fs_copy_prop_dataflow::dump_block_data() const
+{
+   for (int b = 0; b < cfg->num_blocks; b++) {
+      bblock_t *block = cfg->blocks[b];
+      printf("Block %d [%d, %d] (parents ", block->block_num,
+             block->start_ip, block->end_ip);
+      foreach_list(block_node, &block->parents) {
+         bblock_t *parent = ((bblock_link *) block_node)->block;
+         printf("%d ", parent->block_num);
+      }
+      printf("):\n");
+      printf("       livein = 0x");
+      for (int i = 0; i < bitset_words; i++)
+         printf("%08x", bd[b].livein[i]);
+      printf(", liveout = 0x");
+      for (int i = 0; i < bitset_words; i++)
+         printf("%08x", bd[b].liveout[i]);
+      printf(",\n       copy   = 0x");
+      for (int i = 0; i < bitset_words; i++)
+         printf("%08x", bd[b].copy[i]);
+      printf(", kill    = 0x");
+      for (int i = 0; i < bitset_words; i++)
+         printf("%08x", bd[b].kill[i]);
+      printf("\n");
+   }
+}
+
 bool
 fs_visitor::try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry)
 {
@@ -468,7 +524,6 @@ fs_visitor::opt_copy_propagate()
                                           out_acp[b]) || progress;
    }
 
-   #if 0
    /* Do dataflow analysis for those available copies. */
    fs_copy_prop_dataflow dataflow(mem_ctx, &cfg, out_acp);
 
@@ -488,7 +543,6 @@ fs_visitor::opt_copy_propagate()
 
       progress = opt_copy_propagate_local(mem_ctx, block, in_acp) || progress;
    }
-   #endif
 
    for (int i = 0; i < cfg.num_blocks; i++)
       delete [] out_acp[i];