add support for CMPPS and CMPPD instructions (#14593)

This commit is contained in:
Walter Bright 2022-10-26 03:51:20 -07:00 committed by GitHub
parent d747cd0006
commit 3e683fe6fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 111 additions and 16 deletions

View file

@ -247,6 +247,24 @@ void orthxmm(ref CodeBuilder cdb, elem *e, regm_t *pretregs)
getregs(cdb,retregs);
cdb.gen2(op,modregxrmx(3,reg-XMM0,rreg-XMM0));
if (op == CMPPS || op == CMPPD)
{
// https://www.felixcloutier.com/x86/cmpps
ubyte imm8;
switch (e.Eoper)
{
case OPeqeq: imm8 = 0; break;
case OPlt: imm8 = 1; break;
case OPle: imm8 = 2; break;
case OPne: imm8 = 4; break;
default:
elem_print(e);
assert(0); // not doing the unordered compares
}
code* c = cdb.last();
c.IFL2 = FLconst;
c.IEV2.Vsize_t = imm8;
}
checkSetVex(cdb.last(), e1.Ety);
if (retregs != *pretregs)
fixresult(cdb,e,retregs,pretregs);
@ -1121,6 +1139,13 @@ private opcode_t xmmoperator(tym_t tym, OPER oper)
case TYdouble:
case TYidouble: op = UCOMISD; break;
case TYfloat4:
case TYfloat8:
case TYfloat16: op = CMPPS; break;
case TYdouble2:
case TYdouble4:
case TYdouble8: op = CMPPD; break;
default: assert(0);
}
break;

View file

@ -1821,24 +1821,14 @@ elem* toElem(Expression e, IRState *irs)
}
else if (t1.ty == Tvector)
{
/* Rewrite in terms of < operator
*/
bool swap; // swap operands
bool comp; // complement result
switch (eop)
{
case OPgt: break; // x > y
case OPlt: swap = true; break; // y > x
case OPle: comp = true; break; // !(x > y)
case OPge: swap = true; comp = true; break; // !(y > x)
default: assert(0);
}
elem* e1 = toElem(ce.e1, irs);
elem* e2 = toElem(ce.e2, irs);
elem* ex;
if (swap)
tym_t tym = totym(ce.type);
elem* ex; // store side effects in ex
// swap operands
void swapOps()
{
// put side effects of e1 into ex
if (el_sideeffect(e1) && e2.Eoper != OPconst)
@ -1853,7 +1843,49 @@ elem* toElem(Expression e, IRState *irs)
e1 = tmp;
}
tym_t tym = totym(ce.type);
if (t1.isfloating())
{
/* Rewrite in terms of < or <= operator
*/
OPER op;
switch (eop)
{
case OPlt: // x < y
case OPle: // x <= y
op = eop;
break;
case OPgt: op = OPlt; goto Lswap; // y < x
case OPge: op = OPle; goto Lswap; // y <= x
Lswap:
swapOps();
break;
default:
assert(0);
}
e = el_bin(op, tym, e1, e2);
elem_setLoc(e, ce.loc);
e = el_combine(ex, e);
return e;
}
/* Rewrite in terms of > operator
*/
bool swap; // swap operands
bool comp; // complement result
switch (eop)
{
case OPgt: break; // x > y
case OPlt: swap = true; break; // y > x
case OPle: comp = true; break; // !(x > y)
case OPge: swap = true; comp = true; break; // !(y > x)
default: assert(0);
}
if (swap)
swapOps();
if (t1.isunsigned() || t2.isunsigned())
{

View file

@ -150,6 +150,42 @@ void testunscmp()
/*****************************************/
float4 testlt(float4 x, float4 y) { return x < y; }
float4 testgt(float4 x, float4 y) { return x > y; }
float4 testge(float4 x, float4 y) { return x >= y; }
float4 testle(float4 x, float4 y) { return x <= y; }
void testflt()
{
auto x = testgt([5,6,5,6], [4,6,8,7]);
assert((cast(int4)x).array == [-1,0,0,0]);
x = testlt([5,6,5,6], [4,6,8,7]);
assert((cast(int4)x).array == [0,0,-1,-1]);
x = testle([5,6,5,6], [4,6,8,7]);
assert((cast(int4)x).array == [0,-1,-1,-1]);
x = testge([5,6,5,6], [4,6,8,7]);
assert((cast(int4)x).array == [-1,-1,0,0]);
}
double2 testlt(double2 x, double2 y) { return x < y; }
double2 testgt(double2 x, double2 y) { return x > y; }
double2 testge(double2 x, double2 y) { return x >= y; }
double2 testle(double2 x, double2 y) { return x <= y; }
void testdbl()
{
auto x = testgt([5.0,6.0], [4.0,6.0]);
assert((cast(long2)x).array == [-1L,0]);
x = testlt([5.0,6.0], [4.0,6.0]);
assert((cast(long2)x).array == [0L,0]);
x = testle([5.0,6.0], [4.0,6.0]);
assert((cast(long2)x).array == [0L,-1]);
x = testge([5.0,6.0], [4.0,6.0]);
assert((cast(long2)x).array == [-1L,-1]);
}
/*****************************************/
int main()
{
test21474();
@ -160,6 +196,8 @@ int main()
test2();
test3();
testunscmp();
testflt();
testdbl();
return 0;
}