diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp index f9125da873..b2561903e2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp @@ -346,6 +346,11 @@ InstLoc IRBuilder::FoldUOp(unsigned Opcode, InstLoc Op1, unsigned extra) { } } } + if (Opcode == Not) { + if (getOpcode(*Op1) == Not) { + return getOp1(Op1); + } + } return EmitUOp(Opcode, Op1, extra); } @@ -759,10 +764,8 @@ InstLoc IRBuilder::FoldOr(InstLoc Op1, InstLoc Op2) { } // (~A | ~B) == (~(A & B)) - De Morgan's Law - if (InstLoc notOp1 = isNot(Op1)) { - if (InstLoc notOp2 = isNot(Op2)) { - return FoldXor(EmitIntConst(-1U), FoldAnd(notOp1, notOp2)); - } + if (getOpcode(*Op1) == Not && getOpcode(*Op2) == Not) { + return EmitNot(FoldAnd(getOp1(Op1), getOp1(Op2))); } if (Op1 == Op2) return Op1; @@ -778,18 +781,14 @@ InstLoc IRBuilder::FoldXor(InstLoc Op1, InstLoc Op2) { } if (isImm(*Op2)) { if (!GetImmValue(Op2)) return Op1; + if (GetImmValue(Op2) == 0xFFFFFFFFU) { + return EmitNot(Op1); + } if (getOpcode(*Op1) == Xor && isImm(*getOp2(Op1))) { unsigned RHS = GetImmValue(Op2) ^ GetImmValue(getOp2(Op1)); return FoldXor(getOp1(Op1), EmitIntConst(RHS)); } - - // ~(~X) => X - if (GetImmValue(Op2) == -1U) { - if (InstLoc notOp1 = isNot(Op1)) { - return notOp1; - } - } } if (Op1 == Op2) return EmitIntConst(0); @@ -1115,7 +1114,7 @@ unsigned IRBuilder::getNumberOfOperands(InstLoc I) const { numberOfOperands[CInt32] = 0; static unsigned ZeroOp[] = {LoadCR, LoadLink, LoadMSR, LoadGReg, LoadCTR, InterpreterBranch, LoadCarry, RFIExit, LoadFReg, LoadFRegDENToZero, LoadGQR, Int3, }; - static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FSRSqrt, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, }; + static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, Not, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FSRSqrt, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, }; static unsigned BiOp[] = {BranchCond, IdleBranch, And, Xor, Sub, Or, Add, Mul, Rol, Shl, Shrl, Sarl, ICmpEq, ICmpNe, ICmpUgt, ICmpUlt, ICmpSgt, ICmpSlt, ICmpSge, ICmpSle, Store8, Store16, Store32, ICmpCRSigned, ICmpCRUnsigned, InterpreterFallback, StoreSingle, StoreDouble, StorePaired, InsertDoubleInMReg, FSMul, FSAdd, FSSub, FDMul, FDAdd, FDSub, FPAdd, FPMul, FPSub, FPMerge00, FPMerge01, FPMerge10, FPMerge11, FDCmpCR, }; for (size_t i = 0; i < sizeof(ZeroOp) / sizeof(ZeroOp[0]); ++i) { numberOfOperands[ZeroOp[i]] = 0; @@ -1192,26 +1191,6 @@ bool IRBuilder::maskedValueIsZero(InstLoc Op1, InstLoc Op2) const { return (~ComputeKnownZeroBits(Op1) & ~ComputeKnownZeroBits(Op1)) == 0; } -// Returns I' if I == ~I'. -InstLoc IRBuilder::isNot(InstLoc I) const { - if (getOpcode(*I) == Xor) { - const InstLoc Op1 = getOp1(I); - const InstLoc Op2 = getOp2(I); - - // if (-1 ^ x) return x - if (isImm(*Op1) && GetImmValue(Op1) == -1U) { - return Op2; - } - - // if (x ^ -1) return x - if (isImm(*Op2) && GetImmValue(Op2) == -1U) { - return Op1; - } - } - - return NULL; -} - // Returns I' if I == (0 - I') InstLoc IRBuilder::isNeg(InstLoc I) const { if (getOpcode(*I) == Sub && isImm(*getOp1(I)) && GetImmValue(getOp1(I)) == 0) { diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h index 991173c6ed..c18bfeddc2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h @@ -42,6 +42,7 @@ enum Opcode { BSwap32, BSwap16, Cntlzw, // Count leading zeros + Not, Load8, // These loads zext Load16, Load32, @@ -288,7 +289,7 @@ public: return FoldUOp(StoreGReg, value, reg); } InstLoc EmitNot(InstLoc op1) { - return EmitXor(op1, EmitIntConst(0xFFFFFFFFU)); + return FoldUOp(Not, op1); } InstLoc EmitAnd(InstLoc op1, InstLoc op2) { return FoldBiOp(And, op1, op2); @@ -573,7 +574,6 @@ private: unsigned getComplexity(InstLoc I) const; void simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2); bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const; - InstLoc isNot(InstLoc I) const; InstLoc isNeg(InstLoc I) const; std::vector InstList; // FIXME: We must ensure this is diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index fe086179c2..dd71fcac1b 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -768,6 +768,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak case BSwap32: case BSwap16: case Cntlzw: + case Not: case DupSingleToMReg: case DoubleToSingle: case ExpandPackedToMReg: @@ -1072,6 +1073,14 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak regNormalRegClear(RI, I); break; } + case Not: { + if (!thisUsed) break; + X64Reg reg = regBinLHSReg(RI, I); + Jit->NOT(32, R(reg)); + RI.regs[reg] = I; + regNormalRegClear(RI, I); + break; + } case And: { if (!thisUsed) break; regEmitBinInst(RI, I, &JitIL::AND, true); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp index 8e1fb71fe8..f3e25dc2dd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp @@ -198,23 +198,23 @@ void JitIL::crXX(UGeckoInstruction inst) break; case 129: // crandc - ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(0xFFFFFFFFU)); + ecx = ibuild.EmitNot(ecx); eax = ibuild.EmitAnd(eax, ecx); break; case 289: // creqv eax = ibuild.EmitXor(eax, ecx); - eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU)); + eax = ibuild.EmitNot(eax); break; case 225: // crnand eax = ibuild.EmitAnd(eax, ecx); - eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU)); + eax = ibuild.EmitNot(eax); break; case 33: // crnor eax = ibuild.EmitOr(eax, ecx); - eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU)); + eax = ibuild.EmitNot(eax); break; case 449: // cror @@ -222,7 +222,7 @@ void JitIL::crXX(UGeckoInstruction inst) break; case 417: // crorc - ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(0xFFFFFFFFU)); + ecx = ibuild.EmitNot(ecx); eax = ibuild.EmitOr(eax, ecx); break; case 193: diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp index f9316d6e40..45c9100f3d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp @@ -196,13 +196,13 @@ static GekkoOPTemplate table19[] = static GekkoOPTemplate table31[] = { {28, &JitIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {60, &JitIL::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {60, &JitIL::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, {444, &JitIL::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {124, &JitIL::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {124, &JitIL::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, {316, &JitIL::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {412, &JitIL::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {476, &JitIL::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {284, &JitIL::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {412, &JitIL::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {476, &JitIL::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {284, &JitIL::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, {0, &JitIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, {32, &JitIL::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, {26, &JitIL::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},