Adds a couple new IR ops for easy movement of registers between classes.

This commit is contained in:
Ryan Houdek authored and Stefanos Kornilios Mitsis Poiitidis committed 2020-03-06 07:56:01 +02:00
1 parent 9c873d85ec
commit e9be5430b9
5 files changed
+148

No files matched your search

@@ -268,6 +268,39 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
memcpy(GDP, GetSrc<void*>(Op->Header.Args[0]), 16);
break;
}
case IR::OP_VCASTFROMGPR: {
auto Op = IROp->C<IR::IROp_VCastFromGPR>();
memcpy(GDP, GetSrc<void*>(Op->Header.Args[0]), Op->ElementSize);
break;
}
case IR::OP_VEXTRACTTOGPR: {
auto Op = IROp->C<IR::IROp_VExtractToGPR>();
LogMan::Throw::A(Op->RegisterSize <= 16, "OpSize is too large for VExtractToGPR: %d", OpSize);
if (Op->RegisterSize == 16) {
__uint128_t SourceMask = (1ULL << (Op->ElementSize * 8)) - 1;
uint64_t Shift = Op->ElementSize * Op->Idx * 8;
if (Op->ElementSize == 8)
SourceMask = ~0ULL;
__uint128_t Src = *GetSrc<__uint128_t*>(Op->Header.Args[0]);
Src >>= Shift;
Src &= SourceMask;
memcpy(GDP, &Src, Op->ElementSize);
}
else {
uint64_t SourceMask = (1ULL << (Op->ElementSize * 8)) - 1;
uint64_t Shift = Op->ElementSize * Op->Idx * 8;
if (Op->ElementSize == 8)
SourceMask = ~0ULL;
uint64_t Src = *GetSrc<uint64_t*>(Op->Header.Args[0]);
Src >>= Shift;
Src &= SourceMask;
GD = Src;
}
break;
}
case IR::OP_CONSTANT: {
auto Op = IROp->C<IR::IROp_Constant>();
GD = Op->Constant;
+53
View File
@@ -1261,6 +1261,38 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
mov (GetDst<RA_64>(Node), rax);
break;
}
case IR::OP_VEXTRACTTOGPR: {
auto Op = IROp->C<IR::IROp_VExtractToGPR>();
movapd(xmm15, GetSrc(Op->Header.Args[0].ID()));
// Dst_d[Op->DestIdx] = Src2_d[Op->SrcIdx];
// pextrq reg64/mem64, xmm, imm
// pinsrq xmm, reg64/mem64, imm8
switch (Op->ElementSize) {
case 1: {
pextrb(GetDst<RA_8>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
break;
}
case 2: {
pextrw(GetDst<RA_16>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
break;
}
case 4: {
pextrd(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
break;
}
case 8: {
pextrq(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
break;
}
default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break;
}
break;
}
case IR::OP_PRINT: {
auto Op = IROp->C<IR::IROp_Print>();
@@ -1444,6 +1476,27 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
movaps(GetDst(Node), GetSrc(Op->Header.Args[0].ID()));
break;
}
case IR::OP_VCASTFROMGPR: {
auto Op = IROp->C<IR::IROp_VCastFromGPR>();
switch (Op->ElementSize) {
case 1:
movzx(rax, GetSrc<RA_8>(Op->Header.Args[0].ID()));
vmovq(GetDst(Node), rax);
break;
case 2:
movzx(rax, GetSrc<RA_16>(Op->Header.Args[0].ID()));
vmovq(GetDst(Node), rax);
break;
case 4:
vmovd(GetDst(Node), GetSrc<RA_32>(Op->Header.Args[0].ID()).cvt32());
break;
case 8:
vmovq(GetDst(Node), GetSrc<RA_64>(Op->Header.Args[0].ID()).cvt64());
break;
default: LogMan::Msg::A("Unknown castGPR element size: %d", Op->ElementSize);
}
break;
}
case IR::OP_VCMPEQ: {
auto Op = IROp->C<IR::IROp_VCMPEQ>();
LogMan::Throw::A(Op->RegisterSize == 16, "Can't handle register size of: %d", Op->RegisterSize);
@@ -1433,6 +1433,16 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
SetDest(*WrapperOp, BSwap(Src));
break;
}
case IR::OP_VCASTFROMGPR: {
auto Op = IROp->C<IR::IROp_VCastFromGPR>();
LogMan::Throw::A(OpSize <= 16, "Can't handle a vector of size: %d", OpSize);
auto Src = GetSrc(Op->Header.Args[0]);
auto Result = JITState.IRBuilder->CreateVectorSplat(Op->RegisterSize / Op->ElementSize, Src);
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_CREATEVECTOR2: {
auto Op = IROp->C<IR::IROp_CreateVector2>();
LogMan::Throw::A(OpSize <= 16, "Can't handle a vector of size: %d", OpSize);
@@ -1582,7 +1592,32 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VSLI: {
auto Op = IROp->C<IR::IROp_VSLI>();
auto Src = GetSrc(Op->Header.Args[0]);
// Cast to the type we want
Src = CastToOpaqueStructure(Src, Type::getIntNTy(*Con, Src->getType()->getPrimitiveSizeInBits()));
// Now we will do a lshr <NumElements x i1> -> <NumElements x ElementSize>
auto Result = JITState.IRBuilder->CreateShl(Src, JITState.IRBuilder->getIntN(Src->getType()->getPrimitiveSizeInBits(), Op->ByteShift * 8));
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VSRI: {
auto Op = IROp->C<IR::IROp_VSRI>();
auto Src = GetSrc(Op->Header.Args[0]);
// Cast to the type we want
Src = CastToOpaqueStructure(Src, Type::getIntNTy(*Con, Src->getType()->getPrimitiveSizeInBits()));
// Now we will do a lshr <NumElements x i1> -> <NumElements x ElementSize>
auto Result = JITState.IRBuilder->CreateLShr(Src, JITState.IRBuilder->getIntN(Src->getType()->getPrimitiveSizeInBits(), Op->ByteShift * 8));
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VCMPEQ: {
auto Op = IROp->C<IR::IROp_VCMPEQ>();
auto Src1 = GetSrc(Op->Header.Args[0]);
+7
View File
@@ -288,6 +288,13 @@ public:
IRPair<IROp_VSRI> _VSRI(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t ByteShift) {
return _VSRI(ssa0, RegisterSize, ElementSize, ByteShift);
}
IRPair<IROp_VCastFromGPR> _VCastFromGPR(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0) {
return _VCastFromGPR(ssa0, RegisterSize, ElementSize);
}
IRPair<IROp_VExtractToGPR> _VExtractToGPR(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t Index) {
return _VExtractToGPR(ssa0, RegisterSize, ElementSize, Index);
}
IRPair<IROp_Jump> _Jump() {
return _Jump(InvalidNode);
}
+20
View File
@@ -381,6 +381,17 @@
"SSAArgs": "3"
},
"VExtractToGPR": {
"HasDest": true,
"SSAArgs": "1",
"DestSize": "ElementSize",
"Args": [
"uint8_t", "RegisterSize",
"uint8_t", "ElementSize",
"uint8_t", "Idx"
]
},
"Print": {
"SSAArgs": "1"
},
@@ -588,6 +599,15 @@
"SSAArgs": "1"
},
"VCastFromGPR": {
"HasDest": true,
"SSAArgs": "1",
"Args": [
"uint8_t", "RegisterSize",
"uint8_t", "ElementSize"
]
},
"Last": {
"Last": true,
"Args": []