Merge pull request #2074 from lioncash/vuxtl

IR: Handle 256-bit VUXTL/VUXTL2
This commit is contained in:
Ryan Houdek authored and GitHub committed 2022-10-13 13:15:47 -07:00
commit e9f3a5b3e4
4 files changed
+191 -58

No files matched your search

@@ -1784,40 +1784,46 @@ DEF_OP(VSXTL2) {
}
DEF_OP(VUXTL) {
auto Op = IROp->C<IR::IROp_VUXTL>();
const auto Op = IROp->C<IR::IROp_VUXTL>();
const uint8_t OpSize = IROp->Size;
void *Src = GetSrc<void*>(Data->SSAData, Op->Vector);
uint8_t Tmp[16]{};
uint8_t Tmp[Core::CPUState::XMM_AVX_REG_SIZE]{};
const uint8_t Elements = OpSize / Op->Header.ElementSize;
const uint8_t ElementSize = Op->Header.ElementSize;
const uint8_t Elements = OpSize / ElementSize;
const auto Func = [](auto a, auto min, auto max) { return a; };
switch (Op->Header.ElementSize) {
switch (ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP(2, uint16_t, uint8_t, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, uint16_t, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(8, uint64_t, uint32_t, Func, 0, 0)
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
memcpy(GDP, Tmp, OpSize);
}
DEF_OP(VUXTL2) {
auto Op = IROp->C<IR::IROp_VUXTL2>();
const auto Op = IROp->C<IR::IROp_VUXTL2>();
const uint8_t OpSize = IROp->Size;
void *Src = GetSrc<void*>(Data->SSAData, Op->Vector);
uint8_t Tmp[16];
uint8_t Tmp[Core::CPUState::XMM_AVX_REG_SIZE]{};
const uint8_t Elements = OpSize / Op->Header.ElementSize;
const uint8_t ElementSize = Op->Header.ElementSize;
const uint8_t Elements = OpSize / ElementSize;
const auto Func = [](auto a, auto min, auto max) { return a; };
switch (Op->Header.ElementSize) {
switch (ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP_TOP_SRC(2, uint16_t, uint8_t, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP_TOP_SRC(4, uint32_t, uint16_t, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP_TOP_SRC(8, uint64_t, uint32_t, Func, 0, 0)
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
memcpy(GDP, Tmp, OpSize);
}
+101 -24
View File
@@ -4155,34 +4155,111 @@ DEF_OP(VSXTL2) {
}
DEF_OP(VUXTL) {
auto Op = IROp->C<IR::IROp_VUXTL>();
switch (Op->Header.ElementSize) {
case 2:
uxtl(GetDst(Node).V8H(), GetSrc(Op->Vector.ID()).V8B());
break;
case 4:
uxtl(GetDst(Node).V4S(), GetSrc(Op->Vector.ID()).V4H());
break;
case 8:
uxtl(GetDst(Node).V2D(), GetSrc(Op->Vector.ID()).V2S());
break;
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize);
const auto Op = IROp->C<IR::IROp_VUXTL>();
const auto OpSize = IROp->Size;
const auto ElementSize = Op->Header.ElementSize;
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
const auto Dst = GetDst(Node);
const auto Vector = GetSrc(Op->Vector.ID());
if (HostSupportsSVE && Is256Bit) {
// NOTE: See VSXTL implementation for an explanation on why
// UXTB/UXTH/UXTW aren't used, since the same behavior
// concerns applies here, but with zero-extension
// instead of sign-extension.
switch (ElementSize) {
case 2:
ushllb(VTMP1.Z().VnH(), Vector.Z().VnB(), 0);
ushllt(VTMP2.Z().VnH(), Vector.Z().VnB(), 0);
zip1(Dst.Z().VnH(), VTMP1.Z().VnH(), VTMP2.Z().VnH());
break;
case 4:
ushllb(VTMP1.Z().VnS(), Vector.Z().VnH(), 0);
ushllt(VTMP2.Z().VnS(), Vector.Z().VnH(), 0);
zip1(Dst.Z().VnS(), VTMP1.Z().VnS(), VTMP2.Z().VnS());
break;
case 8:
ushllb(VTMP1.Z().VnD(), Vector.Z().VnS(), 0);
ushllt(VTMP2.Z().VnD(), Vector.Z().VnS(), 0);
zip1(Dst.Z().VnD(), VTMP1.Z().VnD(), VTMP2.Z().VnD());
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
} else {
switch (ElementSize) {
case 2:
uxtl(Dst.V8H(), Vector.V8B());
break;
case 4:
uxtl(Dst.V4S(), Vector.V4H());
break;
case 8:
uxtl(Dst.V2D(), Vector.V2S());
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
}
}
DEF_OP(VUXTL2) {
auto Op = IROp->C<IR::IROp_VUXTL2>();
switch (Op->Header.ElementSize) {
case 2:
uxtl2(GetDst(Node).V8H(), GetSrc(Op->Vector.ID()).V16B());
break;
case 4:
uxtl2(GetDst(Node).V4S(), GetSrc(Op->Vector.ID()).V8H());
break;
case 8:
uxtl2(GetDst(Node).V2D(), GetSrc(Op->Vector.ID()).V4S());
break;
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize);
const auto Op = IROp->C<IR::IROp_VUXTL2>();
const auto OpSize = IROp->Size;
const auto ElementSize = Op->Header.ElementSize;
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
const auto Dst = GetDst(Node);
const auto Vector = GetSrc(Op->Vector.ID());
if (HostSupportsSVE && Is256Bit) {
// NOTE: See VSXTL implementation for an explanation on why
// UXTB/UXTH/UXTW aren't used, since the same behavior
// concerns applies here, but with zero-extension
// instead of sign-extension.
switch (ElementSize) {
case 2:
ushllb(VTMP1.Z().VnH(), Vector.Z().VnB(), 0);
ushllt(VTMP2.Z().VnH(), Vector.Z().VnB(), 0);
zip2(Dst.Z().VnH(), VTMP1.Z().VnH(), VTMP2.Z().VnH());
break;
case 4:
ushllb(VTMP1.Z().VnS(), Vector.Z().VnH(), 0);
ushllt(VTMP2.Z().VnS(), Vector.Z().VnH(), 0);
zip2(Dst.Z().VnS(), VTMP1.Z().VnS(), VTMP2.Z().VnS());
break;
case 8:
ushllb(VTMP1.Z().VnD(), Vector.Z().VnS(), 0);
ushllt(VTMP2.Z().VnD(), Vector.Z().VnS(), 0);
zip2(Dst.Z().VnD(), VTMP1.Z().VnD(), VTMP2.Z().VnD());
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
} else {
switch (ElementSize) {
case 2:
uxtl2(Dst.V8H(), Vector.V16B());
break;
case 4:
uxtl2(Dst.V4S(), Vector.V8H());
break;
case 8:
uxtl2(Dst.V2D(), Vector.V4S());
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
}
}
@@ -2353,37 +2353,87 @@ DEF_OP(VSXTL2) {
}
DEF_OP(VUXTL) {
auto Op = IROp->C<IR::IROp_VUXTL>();
switch (Op->Header.ElementSize) {
const auto Op = IROp->C<IR::IROp_VUXTL>();
const auto OpSize = IROp->Size;
const auto ElementSize = Op->Header.ElementSize;
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
const auto Dst = GetDst(Node);
const auto Vector = GetSrc(Op->Vector.ID());
switch (ElementSize) {
case 2:
pmovzxbw(GetDst(Node), GetSrc(Op->Vector.ID()));
break;
if (Is256Bit) {
vpmovzxbw(ToYMM(Dst), Vector);
} else {
vpmovzxbw(Dst, Vector);
}
break;
case 4:
pmovzxwd(GetDst(Node), GetSrc(Op->Vector.ID()));
break;
if (Is256Bit) {
vpmovzxwd(ToYMM(Dst), Vector);
} else {
vpmovzxwd(Dst, Vector);
}
break;
case 8:
pmovzxdq(GetDst(Node), GetSrc(Op->Vector.ID()));
break;
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize);
if (Is256Bit) {
vpmovzxdq(ToYMM(Dst), Vector);
} else {
vpmovzxdq(Dst, Vector);
}
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
}
DEF_OP(VUXTL2) {
auto Op = IROp->C<IR::IROp_VUXTL2>();
uint8_t OpSize = IROp->Size;
const auto Op = IROp->C<IR::IROp_VUXTL2>();
const auto OpSize = IROp->Size;
vpsrldq(GetDst(Node), GetSrc(Op->Vector.ID()), OpSize / 2);
switch (Op->Header.ElementSize) {
case 2:
pmovzxbw(GetDst(Node), GetDst(Node));
break;
case 4:
pmovzxwd(GetDst(Node), GetDst(Node));
break;
case 8:
pmovzxdq(GetDst(Node), GetDst(Node));
break;
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize);
const auto ElementSize = Op->Header.ElementSize;
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
const auto Dst = GetDst(Node);
const auto Vector = GetSrc(Op->Vector.ID());
if (Is256Bit) {
const auto DstYMM = ToYMM(Dst);
vextracti128(Dst, ToYMM(Vector), 1);
switch (ElementSize) {
case 2:
vpmovzxbw(DstYMM, Dst);
break;
case 4:
vpmovzxwd(DstYMM, Dst);
break;
case 8:
vpmovzxdq(DstYMM, Dst);
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
} else {
vpsrldq(Dst, Vector, OpSize / 2);
switch (ElementSize) {
case 2:
vpmovzxbw(Dst, Dst);
break;
case 4:
vpmovzxwd(Dst, Dst);
break;
case 8:
vpmovzxdq(Dst, Dst);
break;
default:
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
break;
}
}
}
+1 -1
View File
@@ -1077,7 +1077,7 @@
},
"FPR = VUXTL2 u8:#RegisterSize, u8:#ElementSize, FPR:$Vector": {
"Desc": ["Zero extends elements from the source element size to the next size up",
"Source elements come from the upper 64bits of the register"
"Source elements come from the upper half of the register"
],
"DestSize": "RegisterSize",
"NumElements": "RegisterSize / (ElementSize << 1)"