JITIL: Optimize compare instruction.

This commit is contained in:
magumagu 2014-06-23 20:34:03 -07:00 committed by Pierre Bourdon
parent 1429fccb97
commit 79cc000d62
3 changed files with 50 additions and 98 deletions

View File

@ -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:

View File

@ -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);
}

View File

@ -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)