|
|
@ -511,8 +511,8 @@ static void A64GetSetElimination(IR::Block& block) { |
|
|
struct RegisterInfo { |
|
|
struct RegisterInfo { |
|
|
IR::Value register_value; |
|
|
IR::Value register_value; |
|
|
TrackingType tracking_type; |
|
|
TrackingType tracking_type; |
|
|
bool set_instruction_present = false; |
|
|
|
|
|
Iterator last_set_instruction; |
|
|
Iterator last_set_instruction; |
|
|
|
|
|
bool set_instruction_present = false; |
|
|
}; |
|
|
}; |
|
|
std::array<RegisterInfo, 31> reg_info; |
|
|
std::array<RegisterInfo, 31> reg_info; |
|
|
std::array<RegisterInfo, 32> vec_info; |
|
|
std::array<RegisterInfo, 32> vec_info; |
|
|
@ -524,26 +524,25 @@ static void A64GetSetElimination(IR::Block& block) { |
|
|
info.last_set_instruction->Invalidate(); |
|
|
info.last_set_instruction->Invalidate(); |
|
|
block.Instructions().erase(info.last_set_instruction); |
|
|
block.Instructions().erase(info.last_set_instruction); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
info.register_value = value; |
|
|
info.register_value = value; |
|
|
info.tracking_type = tracking_type; |
|
|
info.tracking_type = tracking_type; |
|
|
info.set_instruction_present = true; |
|
|
info.set_instruction_present = true; |
|
|
info.last_set_instruction = set_inst; |
|
|
info.last_set_instruction = set_inst; |
|
|
}; |
|
|
}; |
|
|
const auto do_get = [](RegisterInfo& info, Iterator get_inst, TrackingType tracking_type) { |
|
|
|
|
|
// A sequence like
|
|
|
|
|
|
// SetX r1 -> GetW r1, is just reading off the lowest 32-bits of the register
|
|
|
|
|
|
auto const is_lower_32 = tracking_type == TrackingType::W |
|
|
|
|
|
&& info.tracking_type == TrackingType::X; |
|
|
|
|
|
|
|
|
const auto do_get = [&block](RegisterInfo& info, Iterator get_inst, TrackingType tracking_type) { |
|
|
if (!info.register_value.IsEmpty() && info.tracking_type == tracking_type) { |
|
|
if (!info.register_value.IsEmpty() && info.tracking_type == tracking_type) { |
|
|
get_inst->ReplaceUsesWith(info.register_value); |
|
|
get_inst->ReplaceUsesWith(info.register_value); |
|
|
} else if (!info.register_value.IsEmpty() && is_lower_32) { |
|
|
|
|
|
|
|
|
} else if (!info.register_value.IsEmpty() |
|
|
|
|
|
&& tracking_type == TrackingType::W |
|
|
|
|
|
&& info.tracking_type == TrackingType::X) { |
|
|
|
|
|
// A sequence like
|
|
|
|
|
|
// SetX r1 -> GetW r1, is just reading off the lowest 32-bits of the register
|
|
|
if (info.register_value.IsImmediate()) { |
|
|
if (info.register_value.IsImmediate()) { |
|
|
ReplaceUsesWith(*get_inst, true, u32(info.register_value.GetImmediateAsU64() & 0xffff'ffff)); |
|
|
|
|
|
|
|
|
ReplaceUsesWith(*get_inst, true, u32(info.register_value.GetImmediateAsU64())); |
|
|
} else { |
|
|
} else { |
|
|
info = {}; |
|
|
|
|
|
info.register_value = IR::Value(&*get_inst); |
|
|
|
|
|
info.tracking_type = tracking_type; |
|
|
|
|
|
|
|
|
A64::IREmitter ir{block}; |
|
|
|
|
|
ir.SetInsertionPointBefore(&*get_inst); |
|
|
|
|
|
get_inst->ReplaceUsesWith(ir.LeastSignificantWord(IR::U64{info.register_value})); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
info = {}; |
|
|
info = {}; |
|
|
@ -556,27 +555,27 @@ static void A64GetSetElimination(IR::Block& block) { |
|
|
switch (opcode) { |
|
|
switch (opcode) { |
|
|
case IR::Opcode::A64GetW: { |
|
|
case IR::Opcode::A64GetW: { |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
do_get(reg_info.at(index), inst, TrackingType::W); |
|
|
|
|
|
|
|
|
do_get(reg_info[index], inst, TrackingType::W); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64GetX: { |
|
|
case IR::Opcode::A64GetX: { |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
do_get(reg_info.at(index), inst, TrackingType::X); |
|
|
|
|
|
|
|
|
do_get(reg_info[index], inst, TrackingType::X); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64GetS: { |
|
|
case IR::Opcode::A64GetS: { |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
do_get(vec_info.at(index), inst, TrackingType::S); |
|
|
|
|
|
|
|
|
do_get(vec_info[index], inst, TrackingType::S); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64GetD: { |
|
|
case IR::Opcode::A64GetD: { |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
do_get(vec_info.at(index), inst, TrackingType::D); |
|
|
|
|
|
|
|
|
do_get(vec_info[index], inst, TrackingType::D); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64GetQ: { |
|
|
case IR::Opcode::A64GetQ: { |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
do_get(vec_info.at(index), inst, TrackingType::Q); |
|
|
|
|
|
|
|
|
do_get(vec_info[index], inst, TrackingType::Q); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64GetSP: { |
|
|
case IR::Opcode::A64GetSP: { |
|
|
@ -589,27 +588,27 @@ static void A64GetSetElimination(IR::Block& block) { |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64SetW: { |
|
|
case IR::Opcode::A64SetW: { |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
do_set(reg_info.at(index), inst->GetArg(1), inst, TrackingType::W); |
|
|
|
|
|
|
|
|
do_set(reg_info[index], inst->GetArg(1), inst, TrackingType::W); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64SetX: { |
|
|
case IR::Opcode::A64SetX: { |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
const size_t index = A64::RegNumber(inst->GetArg(0).GetA64RegRef()); |
|
|
do_set(reg_info.at(index), inst->GetArg(1), inst, TrackingType::X); |
|
|
|
|
|
|
|
|
do_set(reg_info[index], inst->GetArg(1), inst, TrackingType::X); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64SetS: { |
|
|
case IR::Opcode::A64SetS: { |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
do_set(vec_info.at(index), inst->GetArg(1), inst, TrackingType::S); |
|
|
|
|
|
|
|
|
do_set(vec_info[index], inst->GetArg(1), inst, TrackingType::S); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64SetD: { |
|
|
case IR::Opcode::A64SetD: { |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
do_set(vec_info.at(index), inst->GetArg(1), inst, TrackingType::D); |
|
|
|
|
|
|
|
|
do_set(vec_info[index], inst->GetArg(1), inst, TrackingType::D); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64SetQ: { |
|
|
case IR::Opcode::A64SetQ: { |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
const size_t index = A64::VecNumber(inst->GetArg(0).GetA64VecRef()); |
|
|
do_set(vec_info.at(index), inst->GetArg(1), inst, TrackingType::Q); |
|
|
|
|
|
|
|
|
do_set(vec_info[index], inst->GetArg(1), inst, TrackingType::Q); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case IR::Opcode::A64SetSP: { |
|
|
case IR::Opcode::A64SetSP: { |
|
|
|