if (instr->format == Format::PSEUDO) {
switch (instr->opcode) {
case aco_opcode::p_create_vector:
- return instr->definitions[0].getTemp().type() == RegType::vgpr;
case aco_opcode::p_extract_vector:
case aco_opcode::p_split_vector:
- return instr->operands[0].getTemp().type() == RegType::vgpr;
+ for (Definition def : instr->definitions) {
+ if (def.getTemp().type() == RegType::vgpr)
+ return true;
+ }
+ return false;
case aco_opcode::p_spill:
case aco_opcode::p_reload:
return false;
ctx.branch_wqm[block_idx] = true;
Block& block = ctx.program->blocks[block_idx];
- aco_ptr<Instruction>& branch = block.instructions.back();
-
- if (branch->opcode != aco_opcode::p_branch) {
- assert(!branch->operands.empty() && branch->operands[0].isTemp());
- set_needs_wqm(ctx, branch->operands[0].getTemp());
- }
/* TODO: this sets more branch conditions to WQM than it needs to
* it should be enough to stop at the "exec mask top level" */
if (block->kind & block_kind_top_level) {
if (ctx.loop && ctx.wqm) {
- /* mark all break conditions as WQM */
unsigned block_idx = block->index + 1;
while (!(ctx.program->blocks[block_idx].kind & block_kind_top_level)) {
+ /* flag all break conditions as WQM:
+ * the conditions might be computed outside the nested CF */
if (ctx.program->blocks[block_idx].kind & block_kind_break)
mark_block_wqm(ctx, block_idx);
+ /* flag all blocks as WQM to ensure we enter all (nested) loops in WQM */
+ exec_ctx.info[block_idx].block_needs |= WQM;
block_idx++;
}
} else if (ctx.loop && !ctx.wqm) {
}
}
+ if (instr->format == Format::PSEUDO_BRANCH && ctx.branch_wqm[block->index]) {
+ needs = WQM;
+ propagate_wqm = true;
+ }
+
if (propagate_wqm) {
for (const Operand& op : instr->operands) {
if (op.isTemp()) {
bld.insert(std::move(startpgm));
/* exec seems to need to be manually initialized with combined shaders */
- if (util_bitcount(ctx.program->stage & sw_mask) > 1) {
+ if (util_bitcount(ctx.program->stage & sw_mask) > 1 || (ctx.program->stage & hw_ngg_gs)) {
bld.sop1(Builder::s_mov, bld.exec(Definition(exec_mask)), bld.lm == s2 ? Operand(UINT64_MAX) : Operand(UINT32_MAX));
instructions[0]->definitions.pop_back();
}
/* create phi for loop footer */
aco_ptr<Pseudo_instruction> phi{create_instruction<Pseudo_instruction>(aco_opcode::p_linear_phi, Format::PSEUDO, preds.size(), 1)};
phi->definitions[0] = bld.def(bld.lm);
- if (k == info.num_exec_masks - 1) {
+ if (k == info.num_exec_masks - 1u) {
phi->definitions[0].setFixed(exec);
need_parallelcopy = false;
}
assert(block->instructions.back()->opcode == aco_opcode::p_branch);
block->instructions.pop_back();
- while (!(ctx.info[idx].exec.back().second & mask_type_loop))
+ bool need_parallelcopy = false;
+ while (!(ctx.info[idx].exec.back().second & mask_type_loop)) {
ctx.info[idx].exec.pop_back();
+ need_parallelcopy = true;
+ }
- ctx.info[idx].exec.back().first = bld.pseudo(aco_opcode::p_parallelcopy, bld.def(bld.lm, exec), ctx.info[idx].exec.back().first);
+ if (need_parallelcopy)
+ ctx.info[idx].exec.back().first = bld.pseudo(aco_opcode::p_parallelcopy, bld.def(bld.lm, exec), ctx.info[idx].exec.back().first);
bld.branch(aco_opcode::p_cbranch_nz, bld.exec(ctx.info[idx].exec.back().first), block->linear_succs[1], block->linear_succs[0]);
return;
}
cond = bld.tmp(s1);
Temp exec_mask = ctx.info[idx].exec[exec_idx].first;
exec_mask = bld.sop2(Builder::s_andn2, bld.def(bld.lm), bld.scc(Definition(cond)),
- exec_mask, current_exec);
+ exec_mask, bld.exec(current_exec));
ctx.info[idx].exec[exec_idx].first = exec_mask;
if (ctx.info[idx].exec[exec_idx].second & mask_type_loop)
break;