diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp index b810b850a98..0be1f5b3fc8 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp @@ -123,12 +123,29 @@ AluGroup::add_trans_instructions(AluInstr *instr) if (!instr->has_alu_flag(alu_is_trans) && !m_slots[instr->dest_chan()]) { if (instr->dest() && instr->dest()->pin() == pin_free) { int used_slot = 3; - while (!m_slots[used_slot] && used_slot >= 0) + auto dest = instr->dest(); + int free_mask = 0xf; + + for (auto p : dest->parents()) { + auto alu = p->as_alu(); + if (alu) + free_mask &= alu->allowed_dest_chan_mask(); + } + + for (auto u : dest->uses()) { + free_mask &= u->allowed_src_chan_mask(); + if (!free_mask) + return false; + } + + while ((!m_slots[used_slot] && used_slot >= 0) || !(free_mask & (1 << used_slot))) --used_slot; // if we schedule a non-trans instr into the trans slot, // there should always be some slot that is already used - assert(used_slot >= 0); + if (used_slot < 0) + return false; + instr->dest()->set_chan(used_slot); } }