Merge pull request #1963 from Deftera186/fix/shader-div-fmas-zero-overflow

fix(shader): return +0 when v_div_fmas_f32 cancels with |src2| >= 2^64
This commit is contained in:
Adrià 2026-10-10 08:11:36 +02:00 committed by GitHub
commit dbe8961752
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 5 deletions

View File

@ -302,6 +302,13 @@ constexpr HelperVector HelperVectors[] = {
{0x8c367fd8u, 0xbf976e24u, 0x8c367fd8u, 1u, 0xac367fd8u, 1u, 0x00000000u, 0x0c367fd8u},
{0x00f745cfu, 0x7f7fffffu, 0x00f745cfu, 0u, 0x00f745cfu, 1u, 0x40f745ceu, 0x00000000u},
{0xcb7cf32du, 0xbfe52415u, 0xbf6a1e62u, 0u, 0xcb7cf32du, 0u, 0x4be2692eu, 0x4b7cf32du},
{0x3f800000u, 0x7f7fffffu, 0xff7fffffu, 1u, 0x1f800000u, 0u, 0x00000000u, 0xbf800000u},
{0x3f800000u, 0xf1800000u, 0x71800000u, 1u, 0x3f800000u, 0u, 0x00000000u, 0xbf800000u},
{0x7f7fffffu, 0xbf800000u, 0x7f7fffffu, 1u, 0x7f7fffffu, 1u, 0x00000000u, 0xff7fffffu},
{0x3f800000u, 0xdf800000u, 0x5f800000u, 1u, 0x3f800000u, 0u, 0x00000000u, 0xbf800000u},
{0x5f400000u, 0xdf200000u, 0x7ef00000u, 1u, 0x5f400000u, 0u, 0x00000000u, 0xdf400000u},
{0xe40a117du, 0xbf800000u, 0xe40a117du, 1u, 0xe40a117du, 0u, 0x00000000u, 0x640a117du},
{0x3f800000u, 0xdf7fffffu, 0x5f7fffffu, 1u, 0x3f800000u, 0u, 0x00000000u, 0xbf800000u},
};
struct DivisionVector {

View File

@ -463,15 +463,13 @@ bool TranslationContext::vDivFmasF32(const RdnaInstruction& inst) {
const IrU1 up(ir.Emit(IrOpcode::UGreaterThanEqual32, IrType::U1, {&exponent(*addend).Value(), &ir.Constant(128u)}));
IrValue& power = ir.Emit(IrOpcode::SelectF32, IrType::F32, {&up.Value(), &ir.ConstantF32(18446744073709551616.0f), &ir.ConstantF32(5.42101086242752217e-20f)});
IrValue& plain = ir.Emit(IrOpcode::FPFma32, IrType::F32, {lhs, rhs, addend});
const IrU32 plainExponent = exponent(plain);
const IrU1 plainInfinite(ir.IEqual(ir.BitwiseAnd(ir.BitCastU32(plain), ir.Constant(0x7fffffffu)), ir.Constant(0x7f800000u)));
const IrU1 rescale(ir.LogicalOr(ir.LogicalAnd(up.Value(), ir.IEqual(plainExponent.Value(), ir.Constant(0u))), ir.LogicalAnd(ir.LogicalNot(up.Value()), plainInfinite.Value())));
const IrU1 rescale(ir.LogicalAnd(ir.LogicalNot(up.Value()), plainInfinite.Value()));
IrValue& lhsMagnitude = ir.BitwiseAnd(ir.BitCastU32(*lhs), ir.Constant(0x7fffffffu));
IrValue& rhsMagnitude = ir.BitwiseAnd(ir.BitCastU32(*rhs), ir.Constant(0x7fffffffu));
const IrU1 lhsLarger(ir.UGreaterThan(lhsMagnitude, rhsMagnitude));
const IrU1 scaleLhs(ir.LogicalOr(ir.LogicalAnd(up.Value(), ir.LogicalNot(lhsLarger.Value())), ir.LogicalAnd(ir.LogicalNot(up.Value()), lhsLarger.Value())));
IrValue& scaled = ir.Emit(IrOpcode::SelectF32, IrType::F32, {&scaleLhs.Value(), lhs, rhs});
IrValue& other = ir.Emit(IrOpcode::SelectF32, IrType::F32, {&scaleLhs.Value(), rhs, lhs});
IrValue& scaled = ir.Emit(IrOpcode::SelectF32, IrType::F32, {&lhsLarger.Value(), lhs, rhs});
IrValue& other = ir.Emit(IrOpcode::SelectF32, IrType::F32, {&lhsLarger.Value(), rhs, lhs});
IrValue& rescaled = ir.Emit(IrOpcode::FPFma32, IrType::F32, {&ir.Emit(IrOpcode::FPMul32, IrType::F32, {&scaled, &power}), &other,
&ir.Emit(IrOpcode::FPMul32, IrType::F32, {addend, &power})});
IrValue& afterwards = ir.Emit(IrOpcode::FPMul32, IrType::F32, {&plain, &power});