summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp100
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR.h3
2 files changed, 93 insertions, 10 deletions
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
index 98f0894b13..c06edcb62e 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
@@ -129,6 +129,7 @@ Fix profiled loads/stores to work safely. On 32-bit, one solution is to
#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
#endif
+#include <algorithm>
#include "IR.h"
#include "../PPCTables.h"
#include "../../CoreTiming.h"
@@ -374,6 +375,22 @@ InstLoc IRBuilder::FoldAdd(InstLoc Op1, InstLoc Op2) {
return getOp1(Op1);
}
+ if (InstLoc negOp1 = isNeg(Op1)) {
+ // TODO: Test the folding below
+ // -A + -B --> -(A + B)
+ if (InstLoc negOp2 = isNeg(Op2)) {
+ return FoldSub(EmitIntConst(0), FoldAdd(negOp1, negOp2));
+ }
+
+ // -A + B --> B - A
+ return FoldSub(Op2, negOp1);
+ }
+
+ // A + -B --> A - B
+ if (InstLoc negOp2 = isNeg(Op2)) {
+ return FoldSub(Op1, negOp2);
+ }
+
// TODO: Test the folding below
// (x * i0) + x => x * (i0 + 1)
if (getOpcode(*Op1) == Mul && isImm(*getOp2(Op1)) && isSameValue(getOp1(Op1), Op2)) {
@@ -425,6 +442,12 @@ InstLoc IRBuilder::FoldSub(InstLoc Op1, InstLoc Op2) {
return EmitIntConst(0);
}
+ // TODO: Test the folding below
+ // x - (-A) => x + A
+ if (InstLoc negOp2 = isNeg(Op2)) {
+ return FoldAdd(Op1, negOp2);
+ }
+
// (x - i0) => x + -i0
if (isImm(*Op2)) {
return FoldAdd(Op1, EmitIntConst(-GetImmValue(Op2)));
@@ -566,6 +589,14 @@ InstLoc IRBuilder::FoldMul(InstLoc Op1, InstLoc Op2) {
}
// TODO: Test the folding below
+ // -X * -Y => X * Y
+ if (InstLoc negOp1 = isNeg(Op1)) {
+ if (InstLoc negOp2 = isNeg(Op2)) {
+ return FoldMul(negOp1, negOp2);
+ }
+ }
+
+ // TODO: Test the folding below
// x * (1 << y) => x << y
if (getOpcode(*Op2) == Shl && isImm(*getOp1(Op2)) && GetImmValue(getOp1(Op2)) == 1) {
return FoldShl(Op1, getOp2(Op2));
@@ -1017,6 +1048,12 @@ unsigned IRBuilder::isSameValue(InstLoc Op1, InstLoc Op2) const {
return true;
}
+ if (getNumberOfOperands(Op1) == 2 && getOpcode(*Op1) != StorePaired && getOpcode(*Op1) == getOpcode(*Op2) &&
+ isSameValue(getOp1(Op1), getOp1(Op2)) && isSameValue(getOp2(Op1), getOp2(Op2)))
+ {
+ return true;
+ }
+
return false;
}
@@ -1028,27 +1065,44 @@ unsigned IRBuilder::isSameValue(InstLoc Op1, InstLoc Op2) const {
// 3 -> UOp
// 4 -> BiOp
unsigned IRBuilder::getComplexity(InstLoc I) const {
- static unsigned complexities[256];
- if (complexities[0] == 0) {
- complexities[Nop] = 1;
- complexities[CInt16] = 1;
- complexities[CInt32] = 1;
+ const unsigned Opcode = getOpcode(*I);
+ if (Opcode == Nop || Opcode == CInt16 || Opcode == CInt32) {
+ return 1;
+ }
+
+ const unsigned numberOfOperands = getNumberOfOperands(I);
+ if (numberOfOperands == -1U) {
+ return 0;
+ }
+
+ return numberOfOperands + 2;
+}
+
+
+unsigned IRBuilder::getNumberOfOperands(InstLoc I) const {
+ static unsigned numberOfOperands[256];
+ if (numberOfOperands[0] == 0) {
+ std::fill_n(numberOfOperands, sizeof(numberOfOperands) / sizeof(numberOfOperands[0]), -1U);
+
+ numberOfOperands[Nop] = 0;
+ numberOfOperands[CInt16] = 0;
+ 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 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) {
- complexities[ZeroOp[i]] = 2;
+ numberOfOperands[ZeroOp[i]] = 0;
}
for (size_t i = 0; i < sizeof(UOp) / sizeof(UOp[0]); ++i) {
- complexities[UOp[i]] = 3;
+ numberOfOperands[UOp[i]] = 1;
}
for (size_t i = 0; i < sizeof(BiOp) / sizeof(BiOp[0]); ++i) {
- complexities[BiOp[i]] = 4;
+ numberOfOperands[BiOp[i]] = 2;
}
}
- return complexities[getOpcode(*I)];
+ return numberOfOperands[getOpcode(*I)];
}
// Performs a few simplifications for commutative operators
@@ -1073,7 +1127,7 @@ void IRBuilder::simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2)
return;
}
- // Transform: (op (op V, C1), C2) ==> (op V, (op C1, C2))
+ // (V op C1) op C2 => V + (C1 + C2)
if (getOpcode(*Op1) == Opcode && isImm(*getOp2(Op1)) && isImm(*Op2)) {
const InstLoc Op1Old = Op1;
const InstLoc Op2Old = Op2;
@@ -1081,6 +1135,7 @@ void IRBuilder::simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2)
Op2 = FoldBiOp(Opcode, getOp2(Op1Old), Op2Old);
}
+ // ((V1 op C1) op (V2 op C2)) => ((V1 op V2) op (C1 op C2))
// Transform: (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2))
if (getOpcode(*Op1) == Opcode && isImm(*getOp2(Op1)) && getOpcode(*Op2) == Opcode && isImm(*getOp2(Op2))) {
const InstLoc Op1Old = Op1;
@@ -1088,6 +1143,22 @@ void IRBuilder::simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2)
Op1 = FoldBiOp(Opcode, getOp1(Op1Old), getOp1(Op2Old));
Op2 = FoldBiOp(Opcode, getOp2(Op1Old), getOp2(Op2Old));
}
+
+ // ((w op x) op (y op z)) => (((w op x) op y) op z)
+ if (getOpcode(*Op1) == Opcode && getOpcode(*Op2) == Opcode) {
+ // Sort the operands where the complexities will be descending order.
+ std::pair<unsigned, InstLoc> ops[4];
+ ops[0] = std::make_pair(getComplexity(getOp1(Op1)), getOp1(Op1));
+ ops[1] = std::make_pair(getComplexity(getOp2(Op1)), getOp2(Op1));
+ ops[2] = std::make_pair(getComplexity(getOp1(Op2)), getOp1(Op2));
+ ops[3] = std::make_pair(getComplexity(getOp2(Op2)), getOp2(Op2));
+ std::sort(ops, ops + 4, std::greater<std::pair<unsigned, InstLoc> >());
+
+ const InstLoc Op1Old = Op1;
+ const InstLoc Op2Old = Op2;
+ Op1 = FoldBiOp(Opcode, FoldBiOp(Opcode, ops[0].second, ops[1].second), ops[2].second);
+ Op2 = ops[3].second;
+ }
}
bool IRBuilder::maskedValueIsZero(InstLoc Op1, InstLoc Op2) const {
@@ -1114,4 +1185,13 @@ InstLoc IRBuilder::isNot(InstLoc I) const {
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) {
+ return getOp2(I);
+ }
+
+ return NULL;
+}
+
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
index 970e2cd52f..7e830714ac 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
@@ -557,6 +557,8 @@ public:
IRBuilder() { Reset(); }
+ unsigned getNumberOfOperands(InstLoc I) const;
+
private:
IRBuilder(IRBuilder&); // DO NOT IMPLEMENT
unsigned isSameValue(InstLoc Op1, InstLoc Op2) const;
@@ -564,6 +566,7 @@ private:
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<Inst> InstList; // FIXME: We must ensure this is
// continuous!