mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 08:22:32 +00:00
fix SSA pass. Keep Identity (still useful). Split into 2 ReplaceUses variants
This commit is contained in:
parent
7001cfa347
commit
ccf4701546
@ -177,21 +177,22 @@ void Inst::ClearArgs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::ReplaceUsesWith(Value replacement) {
|
void Inst::ReplaceUsesWith(Value replacement, bool preserve) {
|
||||||
// move uses because SetArg will call UndoUse and would otherwise
|
// Could also do temp_uses = std::move(uses)
|
||||||
// mutate uses while iterating
|
// But clearer this way
|
||||||
#ifdef _DEBUG
|
// Copy since user->SetArg will mutate this->uses
|
||||||
boost::container::list<IR::Use> temp_uses = uses;
|
boost::container::list<IR::Use> temp_uses = uses;
|
||||||
#else
|
|
||||||
boost::container::list<IR::Use> temp_uses = std::move(uses);
|
|
||||||
#endif
|
|
||||||
if (!replacement.IsImmediate()) {
|
|
||||||
for (auto& [user, operand] : temp_uses) {
|
for (auto& [user, operand] : temp_uses) {
|
||||||
DEBUG_ASSERT(user->Arg(operand).Inst() == this);
|
DEBUG_ASSERT(user->Arg(operand).Inst() == this);
|
||||||
user->SetArg(operand, replacement);
|
user->SetArg(operand, replacement);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
if (preserve) {
|
||||||
|
// Still useful to have Identity for indirection.
|
||||||
|
// SSA pass would be more complicated without it
|
||||||
|
ReplaceOpcode(Opcode::Identity);
|
||||||
|
SetArg(0, replacement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::ReplaceOpcode(IR::Opcode opcode) {
|
void Inst::ReplaceOpcode(IR::Opcode opcode) {
|
||||||
|
@ -43,7 +43,7 @@ bool FoldCommutative(IR::Inst& inst, ImmFn&& imm_fn) {
|
|||||||
|
|
||||||
if (is_lhs_immediate && is_rhs_immediate) {
|
if (is_lhs_immediate && is_rhs_immediate) {
|
||||||
const auto result{imm_fn(Arg<T>(lhs), Arg<T>(rhs))};
|
const auto result{imm_fn(Arg<T>(lhs), Arg<T>(rhs))};
|
||||||
inst.ReplaceUsesWith(IR::Value{result});
|
inst.ReplaceUsesWithAndRemove(IR::Value{result});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (is_lhs_immediate && !is_rhs_immediate) {
|
if (is_lhs_immediate && !is_rhs_immediate) {
|
||||||
@ -75,7 +75,7 @@ bool FoldWhenAllImmediates(IR::Inst& inst, Func&& func) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
using Indices = std::make_index_sequence<Common::LambdaTraits<decltype(func)>::NUM_ARGS>;
|
using Indices = std::make_index_sequence<Common::LambdaTraits<decltype(func)>::NUM_ARGS>;
|
||||||
inst.ReplaceUsesWith(EvalImmediates(inst, func, Indices{}));
|
inst.ReplaceUsesWithAndRemove(EvalImmediates(inst, func, Indices{}));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,12 +83,12 @@ template <IR::Opcode op, typename Dest, typename Source>
|
|||||||
void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
|
void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
|
||||||
const IR::Value value{inst.Arg(0)};
|
const IR::Value value{inst.Arg(0)};
|
||||||
if (value.IsImmediate()) {
|
if (value.IsImmediate()) {
|
||||||
inst.ReplaceUsesWith(IR::Value{std::bit_cast<Dest>(Arg<Source>(value))});
|
inst.ReplaceUsesWithAndRemove(IR::Value{std::bit_cast<Dest>(Arg<Source>(value))});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IR::Inst* const arg_inst{value.InstRecursive()};
|
IR::Inst* const arg_inst{value.InstRecursive()};
|
||||||
if (arg_inst->GetOpcode() == reverse) {
|
if (arg_inst->GetOpcode() == reverse) {
|
||||||
inst.ReplaceUsesWith(arg_inst->Arg(0));
|
inst.ReplaceUsesWithAndRemove(arg_inst->Arg(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ void FoldCompositeExtract(IR::Inst& inst, IR::Opcode construct, IR::Opcode inser
|
|||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inst.ReplaceUsesWith(*result);
|
inst.ReplaceUsesWithAndRemove(*result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FoldConvert(IR::Inst& inst, IR::Opcode opposite) {
|
void FoldConvert(IR::Inst& inst, IR::Opcode opposite) {
|
||||||
@ -141,7 +141,7 @@ void FoldConvert(IR::Inst& inst, IR::Opcode opposite) {
|
|||||||
}
|
}
|
||||||
IR::Inst* const producer{value.InstRecursive()};
|
IR::Inst* const producer{value.InstRecursive()};
|
||||||
if (producer->GetOpcode() == opposite) {
|
if (producer->GetOpcode() == opposite) {
|
||||||
inst.ReplaceUsesWith(producer->Arg(0));
|
inst.ReplaceUsesWithAndRemove(producer->Arg(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,9 +152,9 @@ void FoldLogicalAnd(IR::Inst& inst) {
|
|||||||
const IR::Value rhs{inst.Arg(1)};
|
const IR::Value rhs{inst.Arg(1)};
|
||||||
if (rhs.IsImmediate()) {
|
if (rhs.IsImmediate()) {
|
||||||
if (rhs.U1()) {
|
if (rhs.U1()) {
|
||||||
inst.ReplaceUsesWith(inst.Arg(0));
|
inst.ReplaceUsesWithAndRemove(inst.Arg(0));
|
||||||
} else {
|
} else {
|
||||||
inst.ReplaceUsesWith(IR::Value{false});
|
inst.ReplaceUsesWithAndRemove(IR::Value{false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ void FoldLogicalAnd(IR::Inst& inst) {
|
|||||||
void FoldSelect(IR::Inst& inst) {
|
void FoldSelect(IR::Inst& inst) {
|
||||||
const IR::Value cond{inst.Arg(0)};
|
const IR::Value cond{inst.Arg(0)};
|
||||||
if (cond.IsImmediate()) {
|
if (cond.IsImmediate()) {
|
||||||
inst.ReplaceUsesWith(cond.U1() ? inst.Arg(1) : inst.Arg(2));
|
inst.ReplaceUsesWithAndRemove(cond.U1() ? inst.Arg(1) : inst.Arg(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,9 +173,9 @@ void FoldLogicalOr(IR::Inst& inst) {
|
|||||||
const IR::Value rhs{inst.Arg(1)};
|
const IR::Value rhs{inst.Arg(1)};
|
||||||
if (rhs.IsImmediate()) {
|
if (rhs.IsImmediate()) {
|
||||||
if (rhs.U1()) {
|
if (rhs.U1()) {
|
||||||
inst.ReplaceUsesWith(IR::Value{true});
|
inst.ReplaceUsesWithAndRemove(IR::Value{true});
|
||||||
} else {
|
} else {
|
||||||
inst.ReplaceUsesWith(inst.Arg(0));
|
inst.ReplaceUsesWithAndRemove(inst.Arg(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,12 +183,12 @@ void FoldLogicalOr(IR::Inst& inst) {
|
|||||||
void FoldLogicalNot(IR::Inst& inst) {
|
void FoldLogicalNot(IR::Inst& inst) {
|
||||||
const IR::U1 value{inst.Arg(0)};
|
const IR::U1 value{inst.Arg(0)};
|
||||||
if (value.IsImmediate()) {
|
if (value.IsImmediate()) {
|
||||||
inst.ReplaceUsesWith(IR::Value{!value.U1()});
|
inst.ReplaceUsesWithAndRemove(IR::Value{!value.U1()});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IR::Inst* const arg{value.InstRecursive()};
|
IR::Inst* const arg{value.InstRecursive()};
|
||||||
if (arg->GetOpcode() == IR::Opcode::LogicalNot) {
|
if (arg->GetOpcode() == IR::Opcode::LogicalNot) {
|
||||||
inst.ReplaceUsesWith(arg->Arg(0));
|
inst.ReplaceUsesWithAndRemove(arg->Arg(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) {
|
|||||||
}
|
}
|
||||||
IR::Inst* const arg_inst{value.InstRecursive()};
|
IR::Inst* const arg_inst{value.InstRecursive()};
|
||||||
if (arg_inst->GetOpcode() == reverse) {
|
if (arg_inst->GetOpcode() == reverse) {
|
||||||
inst.ReplaceUsesWith(arg_inst->Arg(0));
|
inst.ReplaceUsesWithAndRemove(arg_inst->Arg(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ void FoldAdd(IR::Block& block, IR::Inst& inst) {
|
|||||||
}
|
}
|
||||||
const IR::Value rhs{inst.Arg(1)};
|
const IR::Value rhs{inst.Arg(1)};
|
||||||
if (rhs.IsImmediate() && Arg<T>(rhs) == 0) {
|
if (rhs.IsImmediate() && Arg<T>(rhs) == 0) {
|
||||||
inst.ReplaceUsesWith(inst.Arg(0));
|
inst.ReplaceUsesWithAndRemove(inst.Arg(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +226,8 @@ void FoldCmpClass(IR::Block& block, IR::Inst& inst) {
|
|||||||
} else if ((class_mask & IR::FloatClassFunc::Finite) == IR::FloatClassFunc::Finite) {
|
} else if ((class_mask & IR::FloatClassFunc::Finite) == IR::FloatClassFunc::Finite) {
|
||||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||||
const IR::F32 value = IR::F32{inst.Arg(0)};
|
const IR::F32 value = IR::F32{inst.Arg(0)};
|
||||||
inst.ReplaceUsesWith(ir.LogicalNot(ir.LogicalOr(ir.FPIsInf(value), ir.FPIsInf(value))));
|
inst.ReplaceUsesWithAndRemove(
|
||||||
|
ir.LogicalNot(ir.LogicalOr(ir.FPIsInf(value), ir.FPIsInf(value))));
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -237,7 +238,7 @@ void FoldReadLane(IR::Inst& inst) {
|
|||||||
IR::Inst* prod = inst.Arg(0).InstRecursive();
|
IR::Inst* prod = inst.Arg(0).InstRecursive();
|
||||||
while (prod->GetOpcode() == IR::Opcode::WriteLane) {
|
while (prod->GetOpcode() == IR::Opcode::WriteLane) {
|
||||||
if (prod->Arg(2).U32() == lane) {
|
if (prod->Arg(2).U32() == lane) {
|
||||||
inst.ReplaceUsesWith(prod->Arg(1));
|
inst.ReplaceUsesWithAndRemove(prod->Arg(1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prod = prod->Arg(0).InstRecursive();
|
prod = prod->Arg(0).InstRecursive();
|
||||||
|
@ -25,7 +25,7 @@ void LowerSharedMemToRegisters(IR::Program& program) {
|
|||||||
});
|
});
|
||||||
ASSERT(it != ds_writes.end());
|
ASSERT(it != ds_writes.end());
|
||||||
// Replace data read with value written.
|
// Replace data read with value written.
|
||||||
inst.ReplaceUsesWith((*it)->Arg(1));
|
inst.ReplaceUsesWithAndRemove((*it)->Arg(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -627,7 +627,7 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
|||||||
}
|
}
|
||||||
return ir.ImageSampleImplicitLod(handle, coords, bias, offset, inst_info);
|
return ir.ImageSampleImplicitLod(handle, coords, bias, offset, inst_info);
|
||||||
}();
|
}();
|
||||||
inst.ReplaceUsesWith(new_inst);
|
inst.ReplaceUsesWithAndRemove(new_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
|
void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
|
||||||
|
@ -175,7 +175,13 @@ public:
|
|||||||
void Invalidate();
|
void Invalidate();
|
||||||
void ClearArgs();
|
void ClearArgs();
|
||||||
|
|
||||||
void ReplaceUsesWith(Value replacement);
|
void ReplaceUsesWithAndRemove(Value replacement) {
|
||||||
|
ReplaceUsesWith(replacement, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceUsesWith(Value replacement) {
|
||||||
|
ReplaceUsesWith(replacement, true);
|
||||||
|
}
|
||||||
|
|
||||||
void ReplaceOpcode(IR::Opcode opcode);
|
void ReplaceOpcode(IR::Opcode opcode);
|
||||||
|
|
||||||
@ -212,6 +218,7 @@ private:
|
|||||||
|
|
||||||
void Use(Inst* used, u32 operand);
|
void Use(Inst* used, u32 operand);
|
||||||
void UndoUse(Inst* used, u32 operand);
|
void UndoUse(Inst* used, u32 operand);
|
||||||
|
void ReplaceUsesWith(Value replacement, bool preserve);
|
||||||
|
|
||||||
IR::Opcode op{};
|
IR::Opcode op{};
|
||||||
u32 flags{};
|
u32 flags{};
|
||||||
|
@ -59,6 +59,7 @@ IR::Program TranslateProgram(std::span<const u32> code, Pools& pools, Info& info
|
|||||||
|
|
||||||
// Run optimization passes
|
// Run optimization passes
|
||||||
Shader::Optimization::SsaRewritePass(program.post_order_blocks);
|
Shader::Optimization::SsaRewritePass(program.post_order_blocks);
|
||||||
|
Shader::Optimization::IdentityRemovalPass(program.blocks);
|
||||||
Shader::Optimization::ConstantPropagationPass(program.post_order_blocks);
|
Shader::Optimization::ConstantPropagationPass(program.post_order_blocks);
|
||||||
if (program.info.stage != Stage::Compute) {
|
if (program.info.stage != Stage::Compute) {
|
||||||
Shader::Optimization::LowerSharedMemToRegisters(program);
|
Shader::Optimization::LowerSharedMemToRegisters(program);
|
||||||
|
Loading…
Reference in New Issue
Block a user