[Mesa-dev] [PATCH 1/5] i965: Keep pointers to IF/ELSE/ENDIF instructions in the cfg.

Matt Turner mattst88 at gmail.com
Thu Nov 21 13:57:23 PST 2013


Useful for finding the associated control flow instructions, given a
block ending in one.
---
v2: Handle nested control flow properly. When we reach the ENDIF, we have
    still have the pointers to the IF and ELSE (if it exists).

    The confusing bit of this code is that while bblock_t *cur_if is the
    block that ends in the IF, but cur_else and cur_endif are the blocks
    immediately after the ELSE and ENDIF instructions.

 src/mesa/drivers/dri/i965/brw_cfg.cpp | 33 +++++++++++++++++++++++++++++----
 src/mesa/drivers/dri/i965/brw_cfg.h   | 10 ++++++++++
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_cfg.cpp b/src/mesa/drivers/dri/i965/brw_cfg.cpp
index e9d2bb8..e1a3662 100644
--- a/src/mesa/drivers/dri/i965/brw_cfg.cpp
+++ b/src/mesa/drivers/dri/i965/brw_cfg.cpp
@@ -28,7 +28,7 @@
 #include "brw_fs.h"
 #include "brw_cfg.h"
 
-/** @file brw_cfg_t.cpp
+/** @file brw_cfg.cpp
  *
  * Walks the shader instructions generated and creates a set of basic
  * blocks with successor/predecessor edges connecting them.
@@ -52,6 +52,10 @@ bblock_t::bblock_t() :
 
    parents.make_empty();
    children.make_empty();
+
+   if_inst = NULL;
+   else_inst = NULL;
+   endif_inst = NULL;
 }
 
 void
@@ -142,20 +146,41 @@ cfg_t::create(void *parent_mem_ctx, exec_list *instructions)
 	 set_next_block(next);
 	 break;
 
-      case BRW_OPCODE_ENDIF:
+      case BRW_OPCODE_ENDIF: {
 	 cur_endif->start = (backend_instruction *)inst->next;
 	 cur->add_successor(mem_ctx, cur_endif);
+
 	 set_next_block(cur_endif);
 
-	 if (!cur_else)
+         backend_instruction *else_inst = cur_else ?
+            (backend_instruction *) cur_else->start->prev : NULL;
+
+         assert(cur_if->end->opcode == BRW_OPCODE_IF);
+         assert(!else_inst || else_inst->opcode == BRW_OPCODE_ELSE);
+         assert(inst->opcode == BRW_OPCODE_ENDIF);
+
+         cur_if->if_inst = cur_if->end;
+         cur_if->else_inst = else_inst;
+         cur_if->endif_inst = inst;
+
+	 if (!cur_else) {
 	    cur_if->add_successor(mem_ctx, cur_endif);
+         } else {
+            cur_else->if_inst = cur_if->end;
+            cur_else->else_inst = else_inst;
+            cur_else->endif_inst = inst;
+         }
+
+         cur->if_inst = cur_if->end;
+         cur->else_inst = else_inst;
+         cur->endif_inst = inst;
 
 	 /* Pop the stack so we're in the previous if/else/endif */
 	 cur_if = pop_stack(&if_stack);
 	 cur_else = pop_stack(&else_stack);
 	 cur_endif = pop_stack(&endif_stack);
 	 break;
-
+      }
       case BRW_OPCODE_DO:
 	 /* Push our information onto a stack so we can recover from
 	  * nested loops.
diff --git a/src/mesa/drivers/dri/i965/brw_cfg.h b/src/mesa/drivers/dri/i965/brw_cfg.h
index ec5a3a0..2f5e3f9 100644
--- a/src/mesa/drivers/dri/i965/brw_cfg.h
+++ b/src/mesa/drivers/dri/i965/brw_cfg.h
@@ -56,6 +56,16 @@ public:
    exec_list parents;
    exec_list children;
    int block_num;
+
+   /* If the current basic block ends in an IF, ELSE, or ENDIF instruction,
+    * these pointers will hold the locations of the other associated control
+    * flow instructions.
+    *
+    * Otherwise they are NULL.
+    */
+   backend_instruction *if_inst;
+   backend_instruction *else_inst;
+   backend_instruction *endif_inst;
 };
 
 class cfg_t {
-- 
1.8.3.2



More information about the mesa-dev mailing list