diff --git a/src/amd/compiler/aco_opt_value_numbering.cpp b/src/amd/compiler/aco_opt_value_numbering.cpp index 9aed42974ca..df57a7c4619 100644 --- a/src/amd/compiler/aco_opt_value_numbering.cpp +++ b/src/amd/compiler/aco_opt_value_numbering.cpp @@ -226,7 +226,8 @@ struct InstrPred { case Format::EXP: case Format::SOPP: case Format::PSEUDO_BRANCH: - case Format::PSEUDO_BARRIER: UNREACHABLE("unsupported instruction format"); + case Format::PSEUDO_BARRIER: + case Format::PSEUDO_CALL: UNREACHABLE("unsupported instruction format"); default: return true; } } @@ -360,6 +361,14 @@ process_block(vn_ctx& ctx, Block& block) if (instr->opcode == aco_opcode::p_discard_if || instr->opcode == aco_opcode::p_demote_to_helper || instr->opcode == aco_opcode::p_end_wqm) ctx.exec_id++; + /* Clear all recorded values when encountering a call instruction to prevent replacing + * values across call instructions. The live state that can be kept in registers during + * function calls is typically very limited, so it's better to compute the same thing twice + * instead of increasing live ranges. This also disables value numbering of call instructions + * themselves, which is obviously invalid because callees can have side effects. + */ + if (instr->isCall()) + ctx.expr_values.clear(); /* simple copy-propagation through renaming */ bool copy_instr =