diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h index 19dc72deb62..7e8168f1185 100644 --- a/src/amd/compiler/aco_ir.h +++ b/src/amd/compiler/aco_ir.h @@ -459,8 +459,8 @@ class Operand final { public: constexpr Operand() : reg_(PhysReg{128}), isTemp_(false), isFixed_(true), isConstant_(false), isKill_(false), - isUndef_(true), isFirstKill_(false), constSize(0), isLateKill_(false), is16bit_(false), - is24bit_(false), signext(false) + isUndef_(true), isFirstKill_(false), constSize(0), isLateKill_(false), isClobbered_(false), + is16bit_(false), is24bit_(false), signext(false) {} explicit Operand(Temp r) noexcept @@ -805,6 +805,10 @@ public: constexpr bool isLateKill() const noexcept { return isLateKill_; } + /* Indicates that the Operand's register gets clobbered by the instruction. */ + constexpr void setClobbered(bool flag) noexcept { isClobbered_ = flag; } + constexpr bool isClobbered() const noexcept { return isClobbered_; } + constexpr void setKill(bool flag) noexcept { isKill_ = flag; @@ -874,6 +878,7 @@ private: uint8_t isFirstKill_ : 1; uint8_t constSize : 2; uint8_t isLateKill_ : 1; + uint8_t isClobbered_ : 1; uint8_t is16bit_ : 1; uint8_t is24bit_ : 1; uint8_t signext : 1; diff --git a/src/amd/compiler/aco_live_var_analysis.cpp b/src/amd/compiler/aco_live_var_analysis.cpp index c5c3660c9af..84825e742cd 100644 --- a/src/amd/compiler/aco_live_var_analysis.cpp +++ b/src/amd/compiler/aco_live_var_analysis.cpp @@ -237,6 +237,11 @@ process_live_temps_per_block(live_ctx& ctx, Block* block) insn->operands[1].setLateKill(true); } + /* Check if a definition clobbers some operand */ + int op_idx = get_op_fixed_to_def(insn); + if (op_idx != -1) + insn->operands[op_idx].setClobbered(true); + /* we need to do this in a separate loop because the next one can * setKill() for several operands at once and we don't want to * overwrite that in a later iteration */ @@ -256,8 +261,18 @@ process_live_temps_per_block(live_ctx& ctx, Block* block) Operand& operand = insn->operands[i]; if (!operand.isTemp()) continue; - if (operand.isFixed() && operand.physReg() == vcc) - ctx.program->needs_vcc = true; + if (operand.isFixed() && ctx.program->progress < CompilationProgress::after_ra) { + ctx.program->needs_vcc |= operand.physReg() == vcc; + /* Check if this operand gets overwritten by a precolored definition. */ + if (std::any_of(insn->definitions.begin(), insn->definitions.end(), + [=](Definition def) + { + return def.isFixed() && + def.physReg() + def.size() > operand.physReg() && + operand.physReg() + operand.size() > def.physReg(); + })) + operand.setClobbered(true); + } const Temp temp = operand.getTemp(); if (operand.isKill())