[CPU] Fix f16 pack rounding and SHORT_2 test input
Add round-to-nearest-even to the fast float16 pack path by folding a 0xFFF rounding bias into XMMF16PackLCPI0 and extracting bit 13 of the source as the tie-breaker, matching the software fallback behavior. Fix PACK_SHORT_2 test to use pre-biased float input (0x40400000 = 3.0) as the hardware expects, rather than raw 0.0f which is out of range.
This commit is contained in:
@@ -1152,8 +1152,8 @@ static const vec128_t xmm_consts[] = {
|
||||
*/
|
||||
vec128q(0x7fe000007fe000ULL),
|
||||
|
||||
/* XMMF16PackLCPI0*/
|
||||
vec128i(0x8000000),
|
||||
/* XMMF16PackLCPI0 (bias + round-half-down) */
|
||||
vec128i(0x8000FFF),
|
||||
/*XMMF16PackLCPI2*/
|
||||
vec128i(0x47ffe000),
|
||||
/*XMMF16PackLCPI3*/
|
||||
|
||||
@@ -2600,7 +2600,16 @@ static void emit_fast_f16_unpack(X64Emitter& e, const Inst& i,
|
||||
template <typename Inst>
|
||||
static void emit_fast_f16_pack(X64Emitter& e, const Inst& i,
|
||||
XmmConst final_shuffle) {
|
||||
// XMMF16PackLCPI0 includes bias (0x08000000) + round-half-down (0xFFF).
|
||||
// For round-to-nearest-even, also add the tie-breaker: bit 13 of src.
|
||||
// Bit 13 of (src + bias) == bit 13 of src since the bias doesn't affect
|
||||
// bits 0-26.
|
||||
e.vpaddd(e.xmm1, i.src1, e.GetXmmConstPtr(XMMF16PackLCPI0));
|
||||
e.vpsrld(e.xmm0, i.src1, 13);
|
||||
e.vpslld(e.xmm0, e.xmm0, 31);
|
||||
e.vpsrld(e.xmm0, e.xmm0, 31);
|
||||
e.vpaddd(e.xmm1, e.xmm1, e.xmm0);
|
||||
|
||||
e.vpand(e.xmm2, i.src1, e.GetXmmConstPtr(XMMAbsMaskPS));
|
||||
e.vmovdqa(e.xmm3, e.GetXmmConstPtr(XMMF16PackLCPI2));
|
||||
|
||||
@@ -2769,9 +2778,6 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
|
||||
static void EmitFLOAT16_4(X64Emitter& e, const EmitArgType& i) {
|
||||
if (!i.src1.is_constant) {
|
||||
#if XE_ARCH_AMD64
|
||||
// TODO(has207): this code has an off-by-1 in rounding
|
||||
// compared to the fallback which is accurate, but
|
||||
// keeping it as default. Should be fixed.
|
||||
emit_fast_f16_pack(e, i, XMMPackFLOAT16_4);
|
||||
#else
|
||||
auto src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
|
||||
|
||||
@@ -89,11 +89,15 @@ TEST_CASE("PACK_SHORT_2", "[instr]") {
|
||||
StoreVR(b, 3, b.Pack(LoadVR(b, 4), PACK_TYPE_SHORT_2));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
// SHORT_2 operates on pre-biased floats near 3.0 (0x40400000 = short 0)
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x40400000, 0x40400000, 0, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x43817E00, 0xC37CFC00, 0, 0);
|
||||
|
||||
Reference in New Issue
Block a user