JITIL: Optimize compare instruction.
This commit is contained in:
parent
1429fccb97
commit
79cc000d62
|
@ -550,6 +550,48 @@ static void regEmitICmpInst(RegInfo& RI, InstLoc I, CCFlags flag) {
|
|||
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) {
|
||||
if (isImm(*dest)) {
|
||||
RI.exitNumber++;
|
||||
|
@ -1077,42 +1119,16 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
|||
regEmitICmpInst(RI, I, CC_LE);
|
||||
break;
|
||||
}
|
||||
case ICmpCRUnsigned: {
|
||||
case ICmpCRUnsigned:
|
||||
{
|
||||
if (!thisUsed) break;
|
||||
regEmitCmp(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);
|
||||
regEmitICmpCRInst(RI, I);
|
||||
break;
|
||||
}
|
||||
case ICmpCRSigned: {
|
||||
case ICmpCRSigned:
|
||||
{
|
||||
if (!thisUsed) break;
|
||||
regEmitCmp(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);
|
||||
regEmitICmpCRInst(RI, I);
|
||||
break;
|
||||
}
|
||||
case ConvertFromFastCR:
|
||||
|
|
|
@ -849,42 +849,6 @@ InstLoc IRBuilder::FoldBranchCond(InstLoc Op1, InstLoc Op2) {
|
|||
return EmitBranchUncond(Op2);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -965,38 +929,10 @@ InstLoc IRBuilder::FoldICmp(unsigned Opcode, 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ static void ComputeRC(IREmitter::IRBuilder& ibuild, IREmitter::InstLoc val)
|
|||
{
|
||||
IREmitter::InstLoc res =
|
||||
ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0));
|
||||
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), 0);
|
||||
ibuild.EmitStoreCR(res, 0);
|
||||
}
|
||||
|
||||
void JitILBase::reg_imm(UGeckoInstruction inst)
|
||||
|
@ -114,7 +114,7 @@ void JitILBase::cmpXX(UGeckoInstruction inst)
|
|||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue