mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-26 15:49:50 -06:00
JITIL: Optimize compare instruction.
This commit is contained in:
@ -550,6 +550,48 @@ static void regEmitICmpInst(RegInfo& RI, InstLoc I, CCFlags flag) {
|
|||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void regEmitICmpCRInst(RegInfo& RI, InstLoc I) {
|
||||||
|
bool signed_compare = getOpcode(*I) == ICmpCRSigned;
|
||||||
|
X64Reg reg;
|
||||||
|
if (RI.IInfo[I - RI.FirstI] & 4)
|
||||||
|
{
|
||||||
|
reg = regEnsureInReg(RI, getOp1(I));
|
||||||
|
if (signed_compare)
|
||||||
|
RI.Jit->MOVSX(64, 32, reg, R(reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reg = regFindFreeReg(RI);
|
||||||
|
if (signed_compare)
|
||||||
|
RI.Jit->MOVSX(64, 32, reg, regLocForInst(RI, getOp1(I)));
|
||||||
|
else
|
||||||
|
RI.Jit->MOV(32, R(reg), regLocForInst(RI, getOp1(I)));
|
||||||
|
}
|
||||||
|
if (isImm(*getOp2(I)))
|
||||||
|
{
|
||||||
|
unsigned RHS = RI.Build->GetImmValue(getOp2(I));
|
||||||
|
if (!signed_compare && (RHS & 0x80000000U))
|
||||||
|
{
|
||||||
|
RI.Jit->MOV(32, R(EAX), Imm32(RHS));
|
||||||
|
RI.Jit->SUB(64, R(reg), R(RAX));
|
||||||
|
}
|
||||||
|
else if (RHS)
|
||||||
|
{
|
||||||
|
RI.Jit->SUB(64, R(reg), Imm32(RHS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (signed_compare)
|
||||||
|
RI.Jit->MOVSX(64, 32, RAX, regLocForInst(RI, getOp2(I)));
|
||||||
|
else
|
||||||
|
RI.Jit->MOV(32, R(EAX), regLocForInst(RI, getOp2(I)));
|
||||||
|
RI.Jit->SUB(64, R(reg), R(RAX));
|
||||||
|
}
|
||||||
|
RI.regs[reg] = I;
|
||||||
|
regNormalRegClear(RI, I);
|
||||||
|
}
|
||||||
|
|
||||||
static void regWriteExit(RegInfo& RI, InstLoc dest) {
|
static void regWriteExit(RegInfo& RI, InstLoc dest) {
|
||||||
if (isImm(*dest)) {
|
if (isImm(*dest)) {
|
||||||
RI.exitNumber++;
|
RI.exitNumber++;
|
||||||
@ -1077,42 +1119,16 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
|||||||
regEmitICmpInst(RI, I, CC_LE);
|
regEmitICmpInst(RI, I, CC_LE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ICmpCRUnsigned: {
|
case ICmpCRUnsigned:
|
||||||
|
{
|
||||||
if (!thisUsed) break;
|
if (!thisUsed) break;
|
||||||
regEmitCmp(RI, I);
|
regEmitICmpCRInst(RI, I);
|
||||||
X64Reg reg = regBinReg(RI, I);
|
|
||||||
FixupBranch pLesser = Jit->J_CC(CC_B);
|
|
||||||
FixupBranch pGreater = Jit->J_CC(CC_A);
|
|
||||||
Jit->MOV(32, R(reg), Imm32(0x2)); // _x86Reg == 0
|
|
||||||
FixupBranch continue1 = Jit->J();
|
|
||||||
Jit->SetJumpTarget(pGreater);
|
|
||||||
Jit->MOV(32, R(reg), Imm32(0x4)); // _x86Reg > 0
|
|
||||||
FixupBranch continue2 = Jit->J();
|
|
||||||
Jit->SetJumpTarget(pLesser);
|
|
||||||
Jit->MOV(32, R(reg), Imm32(0x8)); // _x86Reg < 0
|
|
||||||
Jit->SetJumpTarget(continue1);
|
|
||||||
Jit->SetJumpTarget(continue2);
|
|
||||||
RI.regs[reg] = I;
|
|
||||||
regNormalRegClear(RI, I);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ICmpCRSigned: {
|
case ICmpCRSigned:
|
||||||
|
{
|
||||||
if (!thisUsed) break;
|
if (!thisUsed) break;
|
||||||
regEmitCmp(RI, I);
|
regEmitICmpCRInst(RI, I);
|
||||||
X64Reg reg = regBinReg(RI, I);
|
|
||||||
FixupBranch pLesser = Jit->J_CC(CC_L);
|
|
||||||
FixupBranch pGreater = Jit->J_CC(CC_G);
|
|
||||||
Jit->MOV(32, R(reg), Imm32(0x2)); // _x86Reg == 0
|
|
||||||
FixupBranch continue1 = Jit->J();
|
|
||||||
Jit->SetJumpTarget(pGreater);
|
|
||||||
Jit->MOV(32, R(reg), Imm32(0x4)); // _x86Reg > 0
|
|
||||||
FixupBranch continue2 = Jit->J();
|
|
||||||
Jit->SetJumpTarget(pLesser);
|
|
||||||
Jit->MOV(32, R(reg), Imm32(0x8)); // _x86Reg < 0
|
|
||||||
Jit->SetJumpTarget(continue1);
|
|
||||||
Jit->SetJumpTarget(continue2);
|
|
||||||
RI.regs[reg] = I;
|
|
||||||
regNormalRegClear(RI, I);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ConvertFromFastCR:
|
case ConvertFromFastCR:
|
||||||
|
@ -849,42 +849,6 @@ InstLoc IRBuilder::FoldBranchCond(InstLoc Op1, InstLoc Op2) {
|
|||||||
return EmitBranchUncond(Op2);
|
return EmitBranchUncond(Op2);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (getOpcode(*Op1) == And &&
|
|
||||||
isImm(*getOp2(Op1)) &&
|
|
||||||
getOpcode(*getOp1(Op1)) == ICmpCRSigned) {
|
|
||||||
unsigned branchValue = GetImmValue(getOp2(Op1));
|
|
||||||
if (branchValue == 2)
|
|
||||||
return FoldBranchCond(EmitICmpEq(getOp1(getOp1(Op1)),
|
|
||||||
getOp2(getOp1(Op1))), Op2);
|
|
||||||
if (branchValue == 4)
|
|
||||||
return FoldBranchCond(EmitICmpSgt(getOp1(getOp1(Op1)),
|
|
||||||
getOp2(getOp1(Op1))), Op2);
|
|
||||||
if (branchValue == 8)
|
|
||||||
return FoldBranchCond(EmitICmpSlt(getOp1(getOp1(Op1)),
|
|
||||||
getOp2(getOp1(Op1))), Op2);
|
|
||||||
}
|
|
||||||
if (getOpcode(*Op1) == Xor &&
|
|
||||||
isImm(*getOp2(Op1))) {
|
|
||||||
InstLoc XOp1 = getOp1(Op1);
|
|
||||||
unsigned branchValue = GetImmValue(getOp2(Op1));
|
|
||||||
if (getOpcode(*XOp1) == And &&
|
|
||||||
isImm(*getOp2(XOp1)) &&
|
|
||||||
getOpcode(*getOp1(XOp1)) == ICmpCRSigned) {
|
|
||||||
unsigned innerBranchValue =
|
|
||||||
GetImmValue(getOp2(XOp1));
|
|
||||||
if (branchValue == innerBranchValue) {
|
|
||||||
if (branchValue == 2)
|
|
||||||
return FoldBranchCond(EmitICmpNe(getOp1(getOp1(XOp1)),
|
|
||||||
getOp2(getOp1(XOp1))), Op2);
|
|
||||||
if (branchValue == 4)
|
|
||||||
return FoldBranchCond(EmitICmpSle(getOp1(getOp1(XOp1)),
|
|
||||||
getOp2(getOp1(XOp1))), Op2);
|
|
||||||
if (branchValue == 8)
|
|
||||||
return FoldBranchCond(EmitICmpSge(getOp1(getOp1(XOp1)),
|
|
||||||
getOp2(getOp1(XOp1))), Op2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EmitBiOp(BranchCond, Op1, Op2);
|
return EmitBiOp(BranchCond, Op1, Op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -965,38 +929,10 @@ InstLoc IRBuilder::FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InstLoc IRBuilder::FoldICmpCRSigned(InstLoc Op1, InstLoc Op2) {
|
InstLoc IRBuilder::FoldICmpCRSigned(InstLoc Op1, InstLoc Op2) {
|
||||||
if (isImm(*Op1)) {
|
|
||||||
if (isImm(*Op2)) {
|
|
||||||
int c1 = (int)GetImmValue(Op1),
|
|
||||||
c2 = (int)GetImmValue(Op2),
|
|
||||||
result;
|
|
||||||
if (c1 == c2)
|
|
||||||
result = 2;
|
|
||||||
else if (c1 > c2)
|
|
||||||
result = 4;
|
|
||||||
else
|
|
||||||
result = 8;
|
|
||||||
return EmitIntConst(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EmitBiOp(ICmpCRSigned, Op1, Op2);
|
return EmitBiOp(ICmpCRSigned, Op1, Op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstLoc IRBuilder::FoldICmpCRUnsigned(InstLoc Op1, InstLoc Op2) {
|
InstLoc IRBuilder::FoldICmpCRUnsigned(InstLoc Op1, InstLoc Op2) {
|
||||||
if (isImm(*Op1)) {
|
|
||||||
if (isImm(*Op2)) {
|
|
||||||
unsigned int c1 = GetImmValue(Op1),
|
|
||||||
c2 = GetImmValue(Op2),
|
|
||||||
result;
|
|
||||||
if (c1 == c2)
|
|
||||||
result = 2;
|
|
||||||
else if (c1 > c2)
|
|
||||||
result = 4;
|
|
||||||
else
|
|
||||||
result = 8;
|
|
||||||
return EmitIntConst(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EmitBiOp(ICmpCRUnsigned, Op1, Op2);
|
return EmitBiOp(ICmpCRUnsigned, Op1, Op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ static void ComputeRC(IREmitter::IRBuilder& ibuild, IREmitter::InstLoc val)
|
|||||||
{
|
{
|
||||||
IREmitter::InstLoc res =
|
IREmitter::InstLoc res =
|
||||||
ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0));
|
ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0));
|
||||||
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), 0);
|
ibuild.EmitStoreCR(res, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitILBase::reg_imm(UGeckoInstruction inst)
|
void JitILBase::reg_imm(UGeckoInstruction inst)
|
||||||
@ -114,7 +114,7 @@ void JitILBase::cmpXX(UGeckoInstruction inst)
|
|||||||
|
|
||||||
js.downcountAmount++; //TODO: should this be somewhere else?
|
js.downcountAmount++; //TODO: should this be somewhere else?
|
||||||
|
|
||||||
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), inst.CRFD);
|
ibuild.EmitStoreCR(res, inst.CRFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitILBase::boolX(UGeckoInstruction inst)
|
void JitILBase::boolX(UGeckoInstruction inst)
|
||||||
|
Reference in New Issue
Block a user