From b5be03f39f2099d3ca11062929c451370cf8d3f3 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Tue, 16 Mar 2021 10:52:39 +0100 Subject: [PATCH] aco/isel: Fix large inputs being truncated in int32->f16 conversions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous code produced incorrect results for inputs outside the range [INT16_MIN, INT16_MAX]. A problematic case is e.g. i2f16 32768, which previously would be converted to -32768.0 instead of returning the exactly representable floating point result. Reviewed-by: Daniel Schürmann Part-of: --- src/amd/compiler/aco_instruction_selection.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 38794e4dd6f..89b12026a92 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -2453,10 +2453,17 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) src = convert_int(ctx, bld, src, 64, 32, false); } - if (ctx->program->chip_class >= GFX8) { + if (ctx->program->chip_class >= GFX8 && input_size <= 16) { bld.vop1(aco_opcode::v_cvt_f16_i16, Definition(dst), src); } else { - /* GFX7 and earlier do not support direct f16⟷i16 conversions */ + /* Convert to f32 and then down to f16. This is needed to handle + * inputs slightly outside the range [INT16_MIN, INT16_MAX], + * which are representable via f16 but wouldn't be converted + * correctly by v_cvt_f16_i16. + * + * This is also the fallback-path taken on GFX7 and earlier, which + * do not support direct f16⟷i16 conversions. + */ src = bld.vop1(aco_opcode::v_cvt_f32_i32, bld.def(v1), src); bld.vop1(aco_opcode::v_cvt_f16_f32, Definition(dst), src); } @@ -2522,6 +2529,8 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr) } if (ctx->program->chip_class >= GFX8) { + /* float16 has a range of [0, 65519]. Converting from larger + * inputs is UB, so we just need to consider the lower 16 bits */ bld.vop1(aco_opcode::v_cvt_f16_u16, Definition(dst), src); } else { /* GFX7 and earlier do not support direct f16⟷u16 conversions */