r600g/sb: fix scheduling of PRED_SET instructions
authorVadim Girlin <vadimgirlin@gmail.com>
Sun, 26 May 2013 21:39:54 +0000 (01:39 +0400)
committerVadim Girlin <vadimgirlin@gmail.com>
Sun, 26 May 2013 21:45:07 +0000 (01:45 +0400)
PRED_SET instructions that update exec mask should be scheduled immediately
prior to the "if-then-else" block, because any instruction that is
inserted after alu clause with PRED_SET and before conditional block is
also conditionally executed by hw (exec mask is already updated at that
moment).

Propbably it's better to make PRED_SET a part of conditional
"if-then-else" block in the IR to handle this more cleanly,
but for now this temporary solution should prevent the problem.

Signed-off-by: Vadim Girlin <vadimgirlin@gmail.com>
src/gallium/drivers/r600/sb/sb_gcm.cpp
src/gallium/drivers/r600/sb/sb_pass.h

index b09008c6f0851e9dfaaf9532fe1b7b1df0385dea..bccb671396712994b0a4482b95280227f9266c05 100644 (file)
@@ -359,6 +359,13 @@ void gcm::bu_sched_bb(bb_node* bb) {
 
                for (unsigned sq = SQ_CF; sq < SQ_NUM; ++sq) {
 
+                       if (sq == SQ_CF && pending_exec_mask_update) {
+                               pending_exec_mask_update = false;
+                               sq = SQ_ALU;
+                               --sq;
+                               continue;
+                       }
+
                        if (!bu_ready_next[sq].empty())
                                bu_ready[sq].splice(bu_ready[sq].end(), bu_ready_next[sq]);
 
@@ -599,7 +606,14 @@ void gcm::add_ready(node *n) {
                bu_ready_early[sq].push_back(n);
        else if (sq == SQ_ALU && n->is_copy_mov())
                bu_ready[sq].push_front(n);
-       else
+       else if (n->is_alu_inst()) {
+               alu_node *a = static_cast<alu_node*>(n);
+               if (a->bc.op_ptr->flags & AF_PRED && a->dst[2]) {
+                       // PRED_SET instruction that updates exec mask
+                       pending_exec_mask_update = true;
+               }
+               bu_ready_next[sq].push_back(n);
+       } else
                bu_ready_next[sq].push_back(n);
 }
 
index d5d48c3c740ebd5d4856e69f2941adb83c4bb3a5..a6338ae01769dcc35790eb9041dd6b808ab7038e 100644 (file)
@@ -250,13 +250,15 @@ class gcm : public pass {
 
        static const int rp_threshold = 100;
 
+       bool pending_exec_mask_update;
+
 public:
 
        gcm(shader &sh) : pass(sh),
                bu_ready(), bu_ready_next(), bu_ready_early(),
                ready(), op_map(), uses(), nuc_stk(1), ucs_level(),
                bu_bb(), pending_defs(), pending_nodes(), cur_sq(),
-               live(), live_count() {}
+               live(), live_count(), pending_exec_mask_update() {}
 
        virtual int run();