[JIT] Simplify VECTOR_ADD/SUB i32 with saturate

This commit is contained in:
DrChat 2018-03-02 11:48:19 -06:00
parent 131fcd1320
commit 6c97dbaf81
1 changed files with 20 additions and 64 deletions

View File

@ -3779,47 +3779,25 @@ struct VECTOR_ADD
e.vpcmpgtd(e.xmm0, e.xmm2, e.xmm0);
e.vpor(dest, e.xmm1, e.xmm0);
} else {
// Preserve the sources.
if (dest == src1) {
e.vmovdqa(e.xmm2, src1);
src1 = e.xmm2;
}
if (dest == src2) {
e.vmovdqa(e.xmm1, src2);
src2 = e.xmm1;
}
// xmm0 is the only temp register that can be used by
// src1/src2.
e.vpaddd(dest, src1, src2);
e.vpaddd(e.xmm1, src1, src2);
// Overflow results if two inputs are the same sign and the
// result isn't the same sign. if ((s32b)(~(src1 ^ src2) &
// (src1 ^ res)) < 0) then overflowed
// http://locklessinc.com/articles/sat_arithmetic/
e.vpxor(e.xmm1, src1, src2);
// Move src1 to xmm0 in-case it was the same register as the
// dest. This kills src2 if it's a constant.
if (src1 != e.xmm0) {
e.vmovdqa(e.xmm0, src1);
src1 = e.xmm0;
}
e.vpxor(e.xmm2, src1, dest);
e.vpandn(e.xmm1, e.xmm1, e.xmm2);
// High bit of xmm1 is now set if overflowed.
e.vpxor(e.xmm2, src1, src2);
e.vpxor(e.xmm3, src1, e.xmm1);
e.vpandn(e.xmm2, e.xmm2, e.xmm3);
// Set any negative overflowed elements of src1 to INT_MIN
e.vpand(e.xmm2, src1, e.xmm1);
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMSignMaskI32),
e.xmm2);
e.vpand(e.xmm3, src1, e.xmm2);
e.vblendvps(e.xmm1, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32),
e.xmm3);
// Set any positive overflowed elements of src1 to INT_MAX
e.vpandn(e.xmm2, src1, e.xmm1);
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMAbsMaskPS),
e.xmm2);
e.vpandn(e.xmm3, src1, e.xmm2);
e.vblendvps(dest, e.xmm1, e.GetXmmConstPtr(XMMAbsMaskPS),
e.xmm3);
}
} else {
e.vpaddd(dest, src1, src2);
@ -3949,48 +3927,26 @@ struct VECTOR_SUB
e.vpcmpgtd(e.xmm0, e.xmm0, e.xmm2);
e.vpandn(dest, e.xmm0, e.xmm1);
} else {
// Preserve the sources.
if (dest == src1) {
e.vmovdqa(e.xmm2, src1);
src1 = e.xmm2;
}
if (dest == src2) {
e.vmovdqa(e.xmm1, src2);
src2 = e.xmm1;
}
// xmm0 is the only temp register that can be used by
// src1/src2.
e.vpsubd(dest, src1, src2);
e.vpsubd(e.xmm1, src1, src2);
// We can only overflow if the signs of the operands are
// opposite. If signs are opposite and result sign isn't the
// same as src1's sign, we've overflowed. if ((s32b)((src1 ^
// src2) & (src1 ^ res)) < 0) then overflowed
// http://locklessinc.com/articles/sat_arithmetic/
e.vpxor(e.xmm1, src1, src2);
// Move src1 to xmm0 in-case it's the same register as the
// dest. This kills src2 if it's a constant.
if (src1 != e.xmm0) {
e.vmovdqa(e.xmm0, src1);
src1 = e.xmm0;
}
e.vpxor(e.xmm2, src1, dest);
e.vpand(e.xmm1, e.xmm1, e.xmm2);
// High bit of xmm1 is now set if overflowed.
e.vpxor(e.xmm2, src1, src2);
e.vpxor(e.xmm3, src1, e.xmm1);
e.vpand(e.xmm2, e.xmm2, e.xmm3);
// Set any negative overflowed elements of src1 to INT_MIN
e.vpand(e.xmm2, src1, e.xmm1);
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMSignMaskI32),
e.xmm2);
e.vpand(e.xmm3, src1, e.xmm2);
e.vblendvps(e.xmm1, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32),
e.xmm3);
// Set any positive overflowed elements of src1 to INT_MAX
e.vpandn(e.xmm2, src1, e.xmm1);
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMAbsMaskPS),
e.xmm2);
e.vpandn(e.xmm3, src1, e.xmm2);
e.vblendvps(dest, e.xmm1, e.GetXmmConstPtr(XMMAbsMaskPS),
e.xmm3);
}
} else {
e.vpsubd(dest, src1, src2);