[x64] Fix AVX-512 VECTOR_DENORMFLUSH merge-masking & FpRangeSign values

Copy src1 into dest before the masked vrangeps so that unmasked lanes
(normal/inf/NaN values) are preserved via merge-masking. Previously,
when the register allocator assigned different physical registers for
dest and src1, unmasked lanes would retain stale values from dest.

Tested with Intel SDE and AVX-512 cpu to verify.

Also shift unused FpRangeSign constants into bits [3:2] of the vrangeps
immediate, matching the Intel encoding. Only one used in the code was 0
so it was already correct by accident but using the others in the future
would produce incorrect results.
This commit is contained in:
Herman S.
2026-03-21 14:15:58 +09:00
parent 9621400ef6
commit bc37068f90
3 changed files with 47 additions and 5 deletions

View File

@@ -165,7 +165,8 @@ struct VECTOR_DENORMFLUSH
e.vptestnmd(denormal_mask, i.src1,
e.GetXmmConstPtr(XMMSingleDenormalMask));
e.vxorps(e.xmm1, e.xmm1, e.xmm1);
e.vrangeps(i.dest.reg() | denormal_mask, i.src1, e.xmm1,
e.vmovaps(i.dest, i.src1);
e.vrangeps(i.dest.reg() | denormal_mask, i.dest, e.xmm1,
FpRangeSelect::AbsMin | FpRangeSign::OperandA);
return;
}

View File

@@ -47,10 +47,10 @@ constexpr uint8_t AbsMax = 0b11; // Larger absolute value
}; // namespace FpRangeSelect
namespace FpRangeSign {
constexpr uint8_t OperandA = 0b00; // Copy sign of operand A
constexpr uint8_t Preserve = 0b01; // Leave sign as is
constexpr uint8_t Positive = 0b10; // Set Positive
constexpr uint8_t Negative = 0b11; // Set Negative
constexpr uint8_t OperandA = 0b0000; // Copy sign of operand A
constexpr uint8_t Preserve = 0b0100; // Leave sign as is
constexpr uint8_t Positive = 0b1000; // Set Positive
constexpr uint8_t Negative = 0b1100; // Set Negative
}; // namespace FpRangeSign
} // namespace x64