shader: Add floating-point rounding to I2F

This commit is contained in:
ReinUsesLisp 2021-05-10 03:55:09 -03:00 committed by ameerj
parent 3f00a2ad3f
commit 3b6a632237
3 changed files with 42 additions and 35 deletions

View file

@ -1622,84 +1622,86 @@ U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& v
return is_signed ? ConvertFToS(bitsize, value) : ConvertFToU(bitsize, value); return is_signed ? ConvertFToS(bitsize, value) : ConvertFToU(bitsize, value);
} }
F16F32F64 IREmitter::ConvertSToF(size_t dest_bitsize, size_t src_bitsize, const Value& value) { F16F32F64 IREmitter::ConvertSToF(size_t dest_bitsize, size_t src_bitsize, const Value& value,
FpControl control) {
switch (dest_bitsize) { switch (dest_bitsize) {
case 16: case 16:
switch (src_bitsize) { switch (src_bitsize) {
case 8: case 8:
return Inst<F16>(Opcode::ConvertF16S8, value); return Inst<F16>(Opcode::ConvertF16S8, Flags{control}, value);
case 16: case 16:
return Inst<F16>(Opcode::ConvertF16S16, value); return Inst<F16>(Opcode::ConvertF16S16, Flags{control}, value);
case 32: case 32:
return Inst<F16>(Opcode::ConvertF16S32, value); return Inst<F16>(Opcode::ConvertF16S32, Flags{control}, value);
case 64: case 64:
return Inst<F16>(Opcode::ConvertF16S64, value); return Inst<F16>(Opcode::ConvertF16S64, Flags{control}, value);
} }
break; break;
case 32: case 32:
switch (src_bitsize) { switch (src_bitsize) {
case 8: case 8:
return Inst<F32>(Opcode::ConvertF32S8, value); return Inst<F32>(Opcode::ConvertF32S8, Flags{control}, value);
case 16: case 16:
return Inst<F32>(Opcode::ConvertF32S16, value); return Inst<F32>(Opcode::ConvertF32S16, Flags{control}, value);
case 32: case 32:
return Inst<F32>(Opcode::ConvertF32S32, value); return Inst<F32>(Opcode::ConvertF32S32, Flags{control}, value);
case 64: case 64:
return Inst<F32>(Opcode::ConvertF32S64, value); return Inst<F32>(Opcode::ConvertF32S64, Flags{control}, value);
} }
break; break;
case 64: case 64:
switch (src_bitsize) { switch (src_bitsize) {
case 8: case 8:
return Inst<F64>(Opcode::ConvertF64S8, value); return Inst<F64>(Opcode::ConvertF64S8, Flags{control}, value);
case 16: case 16:
return Inst<F64>(Opcode::ConvertF64S16, value); return Inst<F64>(Opcode::ConvertF64S16, Flags{control}, value);
case 32: case 32:
return Inst<F64>(Opcode::ConvertF64S32, value); return Inst<F64>(Opcode::ConvertF64S32, Flags{control}, value);
case 64: case 64:
return Inst<F64>(Opcode::ConvertF64S64, value); return Inst<F64>(Opcode::ConvertF64S64, Flags{control}, value);
} }
break; break;
} }
throw InvalidArgument("Invalid bit size combination dst={} src={}", dest_bitsize, src_bitsize); throw InvalidArgument("Invalid bit size combination dst={} src={}", dest_bitsize, src_bitsize);
} }
F16F32F64 IREmitter::ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const Value& value) { F16F32F64 IREmitter::ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const Value& value,
FpControl control) {
switch (dest_bitsize) { switch (dest_bitsize) {
case 16: case 16:
switch (src_bitsize) { switch (src_bitsize) {
case 8: case 8:
return Inst<F16>(Opcode::ConvertF16U8, value); return Inst<F16>(Opcode::ConvertF16U8, Flags{control}, value);
case 16: case 16:
return Inst<F16>(Opcode::ConvertF16U16, value); return Inst<F16>(Opcode::ConvertF16U16, Flags{control}, value);
case 32: case 32:
return Inst<F16>(Opcode::ConvertF16U32, value); return Inst<F16>(Opcode::ConvertF16U32, Flags{control}, value);
case 64: case 64:
return Inst<F16>(Opcode::ConvertF16U64, value); return Inst<F16>(Opcode::ConvertF16U64, Flags{control}, value);
} }
break; break;
case 32: case 32:
switch (src_bitsize) { switch (src_bitsize) {
case 8: case 8:
return Inst<F32>(Opcode::ConvertF32U8, value); return Inst<F32>(Opcode::ConvertF32U8, Flags{control}, value);
case 16: case 16:
return Inst<F32>(Opcode::ConvertF32U16, value); return Inst<F32>(Opcode::ConvertF32U16, Flags{control}, value);
case 32: case 32:
return Inst<F32>(Opcode::ConvertF32U32, value); return Inst<F32>(Opcode::ConvertF32U32, Flags{control}, value);
case 64: case 64:
return Inst<F32>(Opcode::ConvertF32U64, value); return Inst<F32>(Opcode::ConvertF32U64, Flags{control}, value);
} }
break; break;
case 64: case 64:
switch (src_bitsize) { switch (src_bitsize) {
case 8: case 8:
return Inst<F64>(Opcode::ConvertF64U8, value); return Inst<F64>(Opcode::ConvertF64U8, Flags{control}, value);
case 16: case 16:
return Inst<F64>(Opcode::ConvertF64U16, value); return Inst<F64>(Opcode::ConvertF64U16, Flags{control}, value);
case 32: case 32:
return Inst<F64>(Opcode::ConvertF64U32, value); return Inst<F64>(Opcode::ConvertF64U32, Flags{control}, value);
case 64: case 64:
return Inst<F64>(Opcode::ConvertF64U64, value); return Inst<F64>(Opcode::ConvertF64U64, Flags{control}, value);
} }
break; break;
} }
@ -1707,9 +1709,9 @@ F16F32F64 IREmitter::ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const
} }
F16F32F64 IREmitter::ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed, F16F32F64 IREmitter::ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed,
const Value& value) { const Value& value, FpControl control) {
return is_signed ? ConvertSToF(dest_bitsize, src_bitsize, value) return is_signed ? ConvertSToF(dest_bitsize, src_bitsize, value, control)
: ConvertUToF(dest_bitsize, src_bitsize, value); : ConvertUToF(dest_bitsize, src_bitsize, value, control);
} }
U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) {

View file

@ -291,12 +291,12 @@ public:
[[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value); [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value);
[[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value); [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value);
[[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value); [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value);
[[nodiscard]] F16F32F64 ConvertSToF(size_t dest_bitsize, size_t src_bitsize, [[nodiscard]] F16F32F64 ConvertSToF(size_t dest_bitsize, size_t src_bitsize, const Value& value,
const Value& value); FpControl control = {});
[[nodiscard]] F16F32F64 ConvertUToF(size_t dest_bitsize, size_t src_bitsize, [[nodiscard]] F16F32F64 ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const Value& value,
const Value& value); FpControl control = {});
[[nodiscard]] F16F32F64 ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed, [[nodiscard]] F16F32F64 ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed,
const Value& value); const Value& value, FpControl control = {});
[[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value); [[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value);
[[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value, [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value,

View file

@ -99,7 +99,12 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
} }
const int conversion_src_bitsize{i2f.int_format == IntFormat::U64 ? 64 : 32}; const int conversion_src_bitsize{i2f.int_format == IntFormat::U64 ? 64 : 32};
const int dst_bitsize{BitSize(i2f.float_format)}; const int dst_bitsize{BitSize(i2f.float_format)};
IR::F16F32F64 value{v.ir.ConvertIToF(dst_bitsize, conversion_src_bitsize, is_signed, src)}; const IR::FpControl fp_control{
.no_contraction = false,
.rounding = CastFpRounding(i2f.fp_rounding),
.fmz_mode = IR::FmzMode::DontCare,
};
auto value{v.ir.ConvertIToF(dst_bitsize, conversion_src_bitsize, is_signed, src, fp_control)};
if (i2f.neg != 0) { if (i2f.neg != 0) {
if (i2f.abs != 0 || !is_signed) { if (i2f.abs != 0 || !is_signed) {
// We know the value is positive // We know the value is positive