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); }); MaybeAddSubImm<bitsize>(code, sub ? ~imm : imm, [&](const auto b) { code.ADD(Rresult, *Ra, b); });
} }
} else { } else {
code.MOV(Rscratch0<bitsize>(), imm); ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
sub ? code.SBC(Rresult, Ra, Rscratch0<bitsize>()) : code.ADC(Rresult, Ra, Rscratch0<bitsize>());
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 { } else {
auto Rb = ctx.reg_alloc.ReadReg<bitsize>(args[1]); auto Rb = ctx.reg_alloc.ReadReg<bitsize>(args[1]);
@ -783,6 +793,8 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*
} }
} }
} else { } else {
ctx.reg_alloc.ReadWriteFlags(args[2], nullptr);
sub ? code.SBC(Rresult, Ra, Rb) : code.ADC(Rresult, Ra, Rb); 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 // ASSERT size fits
break; break;
case HostLoc::Kind::Spill: 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; break;
case HostLoc::Kind::Flags: case HostLoc::Kind::Flags:
code.MRS(oaknut::XReg{new_location_index}, oaknut::SystemReg::NZCV); 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"); ASSERT_FALSE("Logic error");
break; break;
case HostLoc::Kind::Spill: 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; break;
case HostLoc::Kind::Flags: case HostLoc::Kind::Flags:
ASSERT_FALSE("Moving from flags into fprs is not currently supported"); 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; fprs[new_location_index].realized = true;
return new_location_index; return new_location_index;
} else if constexpr (required_kind == HostLoc::Kind::Flags) { } 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 { } else {
static_assert(required_kind == HostLoc::Kind::Fpr || required_kind == HostLoc::Kind::Gpr || required_kind == HostLoc::Kind::Flags); 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 { } else {
ASSERT_FALSE("Invalid current location for flags"); ASSERT_FALSE("Invalid current location for flags");
} }
flags.SetupLocation(write);
flags.locked--; if (write) {
flags.realized = false; flags.SetupLocation(write);
flags.locked--;
flags.realized = false;
}
} }
void RegAlloc::SpillFlags() { void RegAlloc::SpillFlags() {

View file

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