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:
commit
dbe8961752
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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});
|
||||
|
|
|
|||
Loading…
Reference in New Issue