From 3a45802514b943fac84d0f27c3109228b73e9c16 Mon Sep 17 00:00:00 2001 From: Georg Lehmann Date: Fri, 6 Jun 2025 16:42:39 +0200 Subject: [PATCH] aco/lower_to_hw: support saturating fp8 conversions Sadly amd only made this behavior controlable with global state. We add a new pseudo opcode for this purpose and change FP16_OVFL for each instruction. Ideally we would only do it once for clauses and after ilp scheduling, but this can be improved in the future. Reviewed-by: Rhys Perry Part-of: --- src/amd/compiler/aco_lower_to_hw_instr.cpp | 14 ++++++++++++++ src/amd/compiler/aco_opcodes.py | 1 + 2 files changed, 15 insertions(+) diff --git a/src/amd/compiler/aco_lower_to_hw_instr.cpp b/src/amd/compiler/aco_lower_to_hw_instr.cpp index 03f4a272d83..4005dd6a779 100644 --- a/src/amd/compiler/aco_lower_to_hw_instr.cpp +++ b/src/amd/compiler/aco_lower_to_hw_instr.cpp @@ -2926,6 +2926,20 @@ lower_to_hw_instr(Program* program) ctx.instructions.emplace_back(std::move(instr)); emit_set_mode(bld, block->fp_mode, set_round, false); + } else if (instr->opcode == aco_opcode::p_v_cvt_pk_fp8_f32_ovfl) { + /* FP8/BF8 uses FP16_OVFL(1) to clamp to max finite result. Temporarily set it for the + * instruction. + * "((size - 1) << 11 | (offset << 6) | register" (MODE is encoded as register 1, we + * want to set a single bit at offset 23) + */ + bld.sopk(aco_opcode::s_setreg_imm32_b32, Operand::literal32(1), + (0 << 11) | (23 << 6) | 1); + + instr->opcode = aco_opcode::v_cvt_pk_fp8_f32; + ctx.instructions.emplace_back(std::move(instr)); + + bld.sopk(aco_opcode::s_setreg_imm32_b32, Operand::literal32(0), + (0 << 11) | (23 << 6) | 1); } else if (instr->isMIMG() && instr->mimg().strict_wqm) { lower_image_sample(&ctx, instr); ctx.instructions.emplace_back(std::move(instr)); diff --git a/src/amd/compiler/aco_opcodes.py b/src/amd/compiler/aco_opcodes.py index 828205161bd..f05691ed326 100644 --- a/src/amd/compiler/aco_opcodes.py +++ b/src/amd/compiler/aco_opcodes.py @@ -1448,6 +1448,7 @@ VOP3 = { ("v_permlane16_var_b32", dst(U32), src(U32, U32), op(gfx12=0x30f)), ("v_permlanex16_var_b32", dst(U32), src(U32, U32), op(gfx12=0x310)), ("v_cvt_pk_fp8_f32", dst(PkF8), src(F32, F32), op(gfx12=0x369)), + ("p_v_cvt_pk_fp8_f32_ovfl", dst(PkF8), src(F32, F32), op(-1)), ("v_cvt_pk_bf8_f32", dst(PkBF8), src(F32, F32), op(gfx12=0x36a)), ("v_cvt_sr_fp8_f32", dst(F8), src(F32, U32), op(gfx12=0x36b)), ("v_cvt_sr_bf8_f32", dst(BF8), src(F32, U32), op(gfx12=0x36c)),