Skip to content

Commit

Permalink
IR: push down AXFLAG lowering
Browse files Browse the repository at this point in the history
so we can get the new axflag optimizations on billy's x13s.

Signed-off-by: Alyssa Rosenzweig <[email protected]>
  • Loading branch information
alyssarosenzweig committed Aug 28, 2024
1 parent 35433cc commit 00e4fe3
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 21 deletions.
19 changes: 17 additions & 2 deletions FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ tags: backend|arm64
$end_info$
*/

#include "CodeEmitter/Emitter.h"
#include "FEXCore/IR/IR.h"
#include "Interface/Context/Context.h"
#include "Interface/Core/JIT/Arm64/JITClass.h"
Expand Down Expand Up @@ -296,8 +297,22 @@ DEF_OP(SetSmallNZV) {
}

DEF_OP(AXFlag) {
LOGMAN_THROW_A_FMT(CTX->HostFeatures.SupportsFlagM2, "Unsupported flagm2 op");
axflag();
if (CTX->HostFeatures.SupportsFlagM2) {
axflag();
} else {
// AXFLAG is defined in the Arm spec as
//
// gt: nzCv -> nzCv
// lt: Nzcv -> nzcv <==> 1 + 0
// eq: nZCv -> nZCv <==> 1 + (~0)
// un: nzCV -> nZcv <==> 0 + 0
//
// For the latter 3 cases, we therefore get the right NZCV by adding V_inv
// to (eq ? ~0 : 0). The remaining case is forced with ccmn.
auto V_inv = GetReg(IROp->Args[0].ID());
csetm(ARMEmitter::Size::i64Bit, TMP1, ARMEmitter::Condition::CC_EQ);
ccmn(ARMEmitter::Size::i64Bit, V_inv, TMP1, ARMEmitter::StatusFlags {0x2} /* nzCv */, ARMEmitter::Condition::CC_LE);
}
}

DEF_OP(CondAddNZCV) {
Expand Down
21 changes: 4 additions & 17 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -2102,22 +2102,9 @@ class OpDispatchBuilder final : public IREmitter {
// Convert NZCV from the Arm representation to an eXternal representation
// that's totally not a euphemism for x86, nuh-uh. But maps to exactly we
// need, what a coincidence!
if (CTX->HostFeatures.SupportsFlagM2) {
_AXFlag();
} else {
// AXFLAG is defined in the Arm spec as
//
// gt: nzCv -> nzCv
// lt: Nzcv -> nzcv <==> 1 + 0
// eq: nZCv -> nZCv <==> 1 + (~0)
// un: nzCV -> nZcv <==> 0 + 0
//
// For the latter 3 cases, we therefore get the right NZCV by adding V_inv
// to (eq ? ~0 : 0). The remaining case is forced with ccmn.
Ref Eq = NZCVSelect(OpSize::i64Bit, {COND_EQ}, _Constant(~0ull), _Constant(0));
_CondAddNZCV(OpSize::i64Bit, V_inv, Eq, {COND_FLEU}, 0x2 /* nzCv */);
}

//
// Our AXFlag emulation on FlagM2-less systems needs V_inv passed.
_AXFlag(CTX->HostFeatures.SupportsFlagM2 ? Invalid() : V_inv);
PossiblySetNZCVBits = ~0;
CFInverted = true;
}
Expand All @@ -2131,7 +2118,7 @@ class OpDispatchBuilder final : public IREmitter {
LOGMAN_THROW_A_FMT(!NZCVDirty, "only expected after fcmp");

// Convert to x86 flags, saves us from or'ing after.
_AXFlag();
_AXFlag(Invalid());
PossiblySetNZCVBits = ~0;
CFInverted = true;

Expand Down
5 changes: 3 additions & 2 deletions FEXCore/Source/Interface/IR/IR.json
Original file line number Diff line number Diff line change
Expand Up @@ -1139,8 +1139,9 @@
"Desc": ["Invert carry flag in NZCV"],
"HasSideEffects": true
},
"AXFlag": {
"Desc": ["After an FCmp, converts NZCV flags from the Arm format to a mysterious eXternal format"],
"AXFlag GPR:$V_inv": {
"Desc": ["After an FCmp, converts NZCV flags from the Arm format to a mysterious eXternal format",
"On FlagM2-less platforms, takes the inverted 1/0 overflow flag"],
"HasSideEffects": true
},
"RmifNZCV GPR:$Src, u8:$Rotate, u8:$Mask": {
Expand Down

0 comments on commit 00e4fe3

Please sign in to comment.