From f4f774f9f64279274f4c501cd78137aabbf16a77 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 27 Jan 2018 01:33:04 +0000 Subject: [PATCH] a64_get_set_elimination_pass: Simplify algorithm --- src/ir_opt/a64_get_set_elimination_pass.cpp | 116 ++++++++++---------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/ir_opt/a64_get_set_elimination_pass.cpp b/src/ir_opt/a64_get_set_elimination_pass.cpp index 3cbd78f9..fc3ee474 100644 --- a/src/ir_opt/a64_get_set_elimination_pass.cpp +++ b/src/ir_opt/a64_get_set_elimination_pass.cpp @@ -17,8 +17,15 @@ namespace Dynarmic::Optimization { void A64GetSetElimination(IR::Block& block) { using Iterator = IR::Block::iterator; + + enum TrackingType { + W, X, + S, D, Q, + SP, NZCV, + }; struct RegisterInfo { IR::Value register_value; + TrackingType tracking_type; bool set_instruction_present = false; Iterator last_set_instruction; }; @@ -27,108 +34,101 @@ void A64GetSetElimination(IR::Block& block) { RegisterInfo sp_info; RegisterInfo nzcv_info; - const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst) { + const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst, TrackingType tracking_type) { if (info.set_instruction_present) { info.last_set_instruction->Invalidate(); block.Instructions().erase(info.last_set_instruction); } info.register_value = value; + info.tracking_type = tracking_type; info.set_instruction_present = true; info.last_set_instruction = set_inst; }; - const auto do_get = [&block](RegisterInfo& info, Iterator get_inst) { - if (info.register_value.IsEmpty()) { + const auto do_get = [&block](RegisterInfo& info, Iterator get_inst, TrackingType tracking_type) { + const auto do_nothing = [&] { + info = {}; info.register_value = IR::Value(&*get_inst); + info.tracking_type = tracking_type; + }; + + if (info.register_value.IsEmpty()) { + do_nothing(); return; } - if (!info.set_instruction_present) { - static const std::vector ordering { - IR::Opcode::A64GetW, - IR::Opcode::A64GetX, - IR::Opcode::A64GetS, - IR::Opcode::A64GetD, - IR::Opcode::A64GetQ, - }; - const auto source_order = std::find(ordering.begin(), ordering.end(), info.register_value.GetInst()->GetOpcode()); - const auto dest_order = std::find(ordering.begin(), ordering.end(), get_inst->GetOpcode()); - if (source_order < dest_order) { - // Zero extension of the value is not appropriate in this case. - // Replace currently known value with the new value. - info.register_value = IR::Value(&*get_inst); - return; - } - } - - if (get_inst->GetType() == info.register_value.GetType()) { + if (info.tracking_type == tracking_type) { get_inst->ReplaceUsesWith(info.register_value); return; } - const IR::Value replacement = [&]() -> IR::Value { - IR::IREmitter ir{block}; - ir.SetInsertionPoint(get_inst); - - const IR::UAny value_to_convert{info.register_value}; - switch (get_inst->GetType()) { - case IR::Type::U8: - return ir.LeastSignificantByte(ir.ZeroExtendToWord(value_to_convert)); - case IR::Type::U16: - return ir.LeastSignificantHalf(ir.ZeroExtendToWord(value_to_convert)); - case IR::Type::U32: - return ir.ZeroExtendToWord(value_to_convert); - case IR::Type::U64: - return ir.ZeroExtendToLong(value_to_convert); - case IR::Type::U128: - return ir.ZeroExtendToQuad(value_to_convert); - default: - UNREACHABLE(); - return {}; - } - }(); - get_inst->ReplaceUsesWith(replacement); + do_nothing(); + return; }; for (auto inst = block.begin(); inst != block.end(); ++inst) { switch (inst->GetOpcode()) { - case IR::Opcode::A64GetW: - case IR::Opcode::A64GetX: { + case IR::Opcode::A64GetW: { const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); - do_get(reg_info.at(index), inst); + do_get(reg_info.at(index), inst, TrackingType::W); + break; + } + case IR::Opcode::A64GetX: { + const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); + do_get(reg_info.at(index), inst, TrackingType::X); + break; + } + case IR::Opcode::A64GetS: { + const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); + do_get(vec_info.at(index), inst, TrackingType::S); + break; + } + case IR::Opcode::A64GetD: { + const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); + do_get(vec_info.at(index), inst, TrackingType::D); break; } - case IR::Opcode::A64GetS: - case IR::Opcode::A64GetD: case IR::Opcode::A64GetQ: { const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); - do_get(vec_info.at(index), inst); + do_get(vec_info.at(index), inst, TrackingType::Q); break; } case IR::Opcode::A64GetSP: { - do_get(sp_info, inst); + do_get(sp_info, inst, TrackingType::SP); + break; + } + case IR::Opcode::A64SetW: { + const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); + do_set(reg_info.at(index), inst->GetArg(1), inst, TrackingType::W); break; } - case IR::Opcode::A64SetW: case IR::Opcode::A64SetX: { const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); - do_set(reg_info.at(index), inst->GetArg(1), inst); + do_set(reg_info.at(index), inst->GetArg(1), inst, TrackingType::X); + break; + } + case IR::Opcode::A64SetS: { + const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); + do_set(vec_info.at(index), inst->GetArg(1), inst, TrackingType::S); + break; + } + case IR::Opcode::A64SetD: { + const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); + do_set(vec_info.at(index), inst->GetArg(1), inst, TrackingType::D); break; } - case IR::Opcode::A64SetS: - case IR::Opcode::A64SetD: case IR::Opcode::A64SetQ: { const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); - do_set(vec_info.at(index), inst->GetArg(1), inst); + do_set(vec_info.at(index), inst->GetArg(1), inst, TrackingType::Q); break; } case IR::Opcode::A64SetSP: { - do_set(sp_info, inst->GetArg(0), inst); + do_set(sp_info, inst->GetArg(0), inst, TrackingType::SP); break; } case IR::Opcode::A64SetNZCV: { - do_set(nzcv_info, inst->GetArg(0), inst); + do_set(nzcv_info, inst->GetArg(0), inst, TrackingType::NZCV); break; } default: {