emit_arm64_data_processing: Fix flag reading in AddSub

Also improve codegen for ZR case.
This commit is contained in:
Merry 2022-07-26 21:46:08 +01:00 committed by merry
parent aaa0773695
commit ff34f4c6ae
3 changed files with 24 additions and 11 deletions

View file

@ -758,8 +758,18 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*
MaybeAddSubImm<bitsize>(code, sub ? ~imm : imm, [&](const auto b) { code.ADD(Rresult, *Ra, b); });
}
} else {
code.MOV(Rscratch0<bitsize>(), imm);
sub ? code.SBC(Rresult, Ra, Rscratch0<bitsize>()) : code.ADC(Rresult, Ra, Rscratch0<bitsize>());
ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
if (imm == 0) {
if constexpr (bitsize == 32) {
sub ? code.SBC(Rresult, Ra, WZR) : code.ADC(Rresult, Ra, WZR);
} else {
sub ? code.SBC(Rresult, Ra, XZR) : code.ADC(Rresult, Ra, XZR);
}
} else {
code.MOV(Rscratch0<bitsize>(), imm);
sub ? code.SBC(Rresult, Ra, Rscratch0<bitsize>()) : code.ADC(Rresult, Ra, Rscratch0<bitsize>());
}
}
} else {
auto Rb = ctx.reg_alloc.ReadReg<bitsize>(args[1]);
@ -783,6 +793,8 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*
}
}
} else {
ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
sub ? code.SBC(Rresult, Ra, Rb) : code.ADC(Rresult, Ra, Rb);
}
}

View file

@ -274,7 +274,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
// ASSERT size fits
break;
case HostLoc::Kind::Spill:
code.LDR(oaknut::XReg{new_location_index}, SP, spill_offset + new_location_index * spill_slot_size);
code.LDR(oaknut::XReg{new_location_index}, SP, spill_offset + current_location->index * spill_slot_size);
break;
case HostLoc::Kind::Flags:
code.MRS(oaknut::XReg{new_location_index}, oaknut::SystemReg::NZCV);
@ -296,7 +296,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
ASSERT_FALSE("Logic error");
break;
case HostLoc::Kind::Spill:
code.LDR(oaknut::QReg{new_location_index}, SP, spill_offset + new_location_index * spill_slot_size);
code.LDR(oaknut::QReg{new_location_index}, SP, spill_offset + current_location->index * spill_slot_size);
break;
case HostLoc::Kind::Flags:
ASSERT_FALSE("Moving from flags into fprs is not currently supported");
@ -307,7 +307,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
fprs[new_location_index].realized = true;
return new_location_index;
} else if constexpr (required_kind == HostLoc::Kind::Flags) {
ASSERT_FALSE("Loading flags back into NZCV is not currently supported");
ASSERT_FALSE("A simple read from flags is likely a logic error.");
} else {
static_assert(required_kind == HostLoc::Kind::Fpr || required_kind == HostLoc::Kind::Gpr || required_kind == HostLoc::Kind::Flags);
}
@ -399,9 +399,12 @@ void RegAlloc::ReadWriteFlags(Argument& read, IR::Inst* write) {
} else {
ASSERT_FALSE("Invalid current location for flags");
}
flags.SetupLocation(write);
flags.locked--;
flags.realized = false;
if (write) {
flags.SetupLocation(write);
flags.locked--;
flags.realized = false;
}
}
void RegAlloc::SpillFlags() {

View file

@ -153,8 +153,6 @@ public:
auto ReadH(Argument& arg) { return RAReg<oaknut::HReg>{*this, false, arg.value}; }
auto ReadB(Argument& arg) { return RAReg<oaknut::BReg>{*this, false, arg.value}; }
auto ReadFlags(Argument& arg) { return RAReg<FlagsTag>{*this, false, arg.value}; }
template<size_t size>
auto ReadReg(Argument& arg) {
if constexpr (size == 64) {
@ -300,7 +298,7 @@ RAReg<T>::~RAReg() {
HostLocInfo& info = reg_alloc.ValueInfo(value.GetInst());
info.locked--;
if (reg) {
info.realized = false;
reg_alloc.ValueInfo(HostLoc{kind, reg->index()}).realized = false;
}
}
}