Added optimizations for combining conditions together when their results are OR'ed
Added recognition of impossible comparisons via NZM and optimize them away Recognize (x + -y) and transform to (x - y) for constants Recognize (~x ) + 1 and transform to -x Check and transform comparisons if theyre semantically equal to others Detect comparisons of single-bit values with their only possible non-zero value and transform to true/false tests Transform ==0 to IS_FALSE, !=0 to IS_TRUE Truncate to int8 if operand for IS_TRUE/IS_FALSE has a nzm of 1 Reduced code generated for SubDidCarry slightly Add special case for InstrEmit_srawix if mask == 1 Cut down the code generated for trap instructions, instead of naive or'ing or compare results do a switch and select the best condition Rerun simplification pass until no changes, as some optimizations will enable others to be done Enable rel32 call optimization by default
This commit is contained in:
@@ -30,9 +30,11 @@ Value* AddDidCarry(PPCHIRBuilder& f, Value* v1, Value* v2) {
|
||||
}
|
||||
|
||||
Value* SubDidCarry(PPCHIRBuilder& f, Value* v1, Value* v2) {
|
||||
Value* trunc_v2 = f.Truncate(v2, INT32_TYPE);
|
||||
|
||||
return f.Or(f.CompareUGT(f.Truncate(v1, INT32_TYPE),
|
||||
f.Not(f.Neg(f.Truncate(v2, INT32_TYPE)))),
|
||||
f.IsFalse(f.Truncate(v2, INT32_TYPE)));
|
||||
f.Sub(trunc_v2, f.LoadConstantInt32(1))),
|
||||
f.IsFalse(trunc_v2));
|
||||
}
|
||||
|
||||
// https://github.com/sebastianbiallas/pearpc/blob/0b3c823f61456faa677f6209545a7b906e797421/src/cpu/cpu_generic/ppc_tools.h#L26
|
||||
@@ -1299,8 +1301,15 @@ int InstrEmit_srawix(PPCHIRBuilder& f, const InstrData& i) {
|
||||
// CA is set if any bits are shifted out of the right and if the result
|
||||
// is negative.
|
||||
uint32_t mask = (uint32_t)XEMASK(64 - i.X.RB, 63);
|
||||
ca = f.And(f.Truncate(f.Shr(v, 31), INT8_TYPE),
|
||||
f.IsTrue(f.And(v, f.LoadConstantUint32(mask))));
|
||||
|
||||
if (mask == 1) {
|
||||
ca = f.And(f.CompareSLT(v, f.LoadConstantInt32(0)),
|
||||
f.Truncate(v, INT8_TYPE));
|
||||
|
||||
} else {
|
||||
ca = f.And(f.CompareSLT(v, f.LoadConstantInt32(0)),
|
||||
f.IsTrue(f.And(v, f.LoadConstantUint32(mask))));
|
||||
}
|
||||
|
||||
v = f.Sha(v, (int8_t)i.X.RB), v = f.SignExtend(v, INT64_TYPE);
|
||||
}
|
||||
|
||||
@@ -440,6 +440,9 @@ int InstrEmit_sc(PPCHIRBuilder& f, const InstrData& i) {
|
||||
|
||||
// Trap (A-25)
|
||||
|
||||
constexpr uint32_t TRAP_SLT = 1 << 4, TRAP_SGT = 1 << 3, TRAP_EQ = 1 << 2,
|
||||
TRAP_ULT = 1 << 1, TRAP_UGT = 1;
|
||||
|
||||
int InstrEmit_trap(PPCHIRBuilder& f, const InstrData& i, Value* va, Value* vb,
|
||||
uint32_t TO) {
|
||||
// if (a < b) & TO[0] then TRAP
|
||||
@@ -454,30 +457,58 @@ int InstrEmit_trap(PPCHIRBuilder& f, const InstrData& i, Value* va, Value* vb,
|
||||
return 0;
|
||||
}
|
||||
Value* v = nullptr;
|
||||
if (TO & (1 << 4)) {
|
||||
// a < b
|
||||
auto cmp = f.CompareSLT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & (1 << 3)) {
|
||||
// a > b
|
||||
auto cmp = f.CompareSGT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & (1 << 2)) {
|
||||
// a = b
|
||||
auto cmp = f.CompareEQ(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & (1 << 1)) {
|
||||
// a <u b
|
||||
auto cmp = f.CompareULT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & (1 << 0)) {
|
||||
// a >u b
|
||||
auto cmp = f.CompareUGT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
|
||||
switch (TO) {
|
||||
case TRAP_SLT | TRAP_EQ: {
|
||||
v = f.CompareSLE(va, vb);
|
||||
break;
|
||||
}
|
||||
case TRAP_SGT | TRAP_EQ: {
|
||||
v = f.CompareSGE(va, vb);
|
||||
break;
|
||||
}
|
||||
case TRAP_ULT | TRAP_EQ: {
|
||||
v = f.CompareULE(va, vb);
|
||||
break;
|
||||
}
|
||||
case TRAP_UGT | TRAP_EQ: {
|
||||
v = f.CompareUGE(va, vb);
|
||||
break;
|
||||
}
|
||||
case TRAP_SGT | TRAP_SLT:
|
||||
case TRAP_UGT | TRAP_ULT: { // used anywhere?
|
||||
v = f.CompareNE(va, vb);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// if (TO == )
|
||||
if (TO & TRAP_SLT) {
|
||||
// a < b
|
||||
auto cmp = f.CompareSLT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & TRAP_SGT) {
|
||||
// a > b
|
||||
auto cmp = f.CompareSGT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & TRAP_EQ) {
|
||||
// a = b
|
||||
auto cmp = f.CompareEQ(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & TRAP_ULT) {
|
||||
// a <u b
|
||||
auto cmp = f.CompareULT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
if (TO & TRAP_UGT) {
|
||||
// a >u b
|
||||
auto cmp = f.CompareUGT(va, vb);
|
||||
v = v ? f.Or(v, cmp) : cmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (v) {
|
||||
f.TrapTrue(v);
|
||||
|
||||
Reference in New Issue
Block a user