summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Girlin <vadimgirlin@gmail.com>2013-05-27 01:39:54 +0400
committerVadim Girlin <vadimgirlin@gmail.com>2013-05-27 01:45:07 +0400
commitff2a6116992a6592747105fb167cab18603361c0 (patch)
treed5acba597f983392c04a757a90dd422bc675a73d
parent44a117ab9ac7e18ffddf4d59ae35fe2c266efc1d (diff)
r600g/sb: fix scheduling of PRED_SET instructions
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>
-rw-r--r--src/gallium/drivers/r600/sb/sb_gcm.cpp16
-rw-r--r--src/gallium/drivers/r600/sb/sb_pass.h4
2 files changed, 18 insertions, 2 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_gcm.cpp b/src/gallium/drivers/r600/sb/sb_gcm.cpp
index b09008c6f08..bccb6713967 100644
--- a/src/gallium/drivers/r600/sb/sb_gcm.cpp
+++ b/src/gallium/drivers/r600/sb/sb_gcm.cpp
@@ -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);
}
diff --git a/src/gallium/drivers/r600/sb/sb_pass.h b/src/gallium/drivers/r600/sb/sb_pass.h
index d5d48c3c740..a6338ae0176 100644
--- a/src/gallium/drivers/r600/sb/sb_pass.h
+++ b/src/gallium/drivers/r600/sb/sb_pass.h
@@ -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();