From e2cb9c57a28c15adeb13955257275352fd148c93 Mon Sep 17 00:00:00 2001 From: Georg Lehmann Date: Sat, 6 Apr 2024 11:07:37 +0200 Subject: [PATCH] aco: use v_interp_p2_f16 opsel Reviewed-by: Rhys Perry Part-of: --- src/amd/compiler/aco_assembler.cpp | 7 ++++++- src/amd/compiler/aco_ir.cpp | 1 + src/amd/compiler/aco_opcodes.py | 4 ++++ src/amd/compiler/aco_optimizer.cpp | 1 + src/amd/compiler/aco_register_allocation.cpp | 5 ++++- src/amd/compiler/aco_validate.cpp | 6 ++++-- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/amd/compiler/aco_assembler.cpp b/src/amd/compiler/aco_assembler.cpp index c4f95ec97d8..961cce9d20b 100644 --- a/src/amd/compiler/aco_assembler.cpp +++ b/src/amd/compiler/aco_assembler.cpp @@ -369,7 +369,8 @@ emit_vintrp_instruction(asm_context& ctx, std::vector& out, Instructio if (instr->opcode == aco_opcode::v_interp_p1ll_f16 || instr->opcode == aco_opcode::v_interp_p1lv_f16 || instr->opcode == aco_opcode::v_interp_p2_legacy_f16 || - instr->opcode == aco_opcode::v_interp_p2_f16) { + instr->opcode == aco_opcode::v_interp_p2_f16 || + instr->opcode == aco_opcode::v_interp_p2_hi_f16) { if (ctx.gfx_level == GFX8 || ctx.gfx_level == GFX9) { encoding = (0b110100 << 26); } else if (ctx.gfx_level >= GFX10) { @@ -378,7 +379,10 @@ emit_vintrp_instruction(asm_context& ctx, std::vector& out, Instructio unreachable("Unknown gfx_level."); } + unsigned opsel = instr->opcode == aco_opcode::v_interp_p2_hi_f16 ? 0x8 : 0; + encoding |= opcode << 16; + encoding |= opsel << 11; encoding |= reg(ctx, instr->definitions[0], 8); out.push_back(encoding); @@ -388,6 +392,7 @@ emit_vintrp_instruction(asm_context& ctx, std::vector& out, Instructio encoding |= interp.high_16bits << 8; encoding |= reg(ctx, instr->operands[0]) << 9; if (instr->opcode == aco_opcode::v_interp_p2_f16 || + instr->opcode == aco_opcode::v_interp_p2_hi_f16 || instr->opcode == aco_opcode::v_interp_p2_legacy_f16 || instr->opcode == aco_opcode::v_interp_p1lv_f16) { encoding |= reg(ctx, instr->operands[2]) << 18; diff --git a/src/amd/compiler/aco_ir.cpp b/src/amd/compiler/aco_ir.cpp index 8d457ee43fe..8d6760695a5 100644 --- a/src/amd/compiler/aco_ir.cpp +++ b/src/amd/compiler/aco_ir.cpp @@ -595,6 +595,7 @@ instr_is_16bit(amd_gfx_level gfx_level, aco_opcode op) case aco_opcode::v_fma_legacy_f16: case aco_opcode::v_div_fixup_legacy_f16: return false; case aco_opcode::v_interp_p2_f16: + case aco_opcode::v_interp_p2_hi_f16: case aco_opcode::v_fma_mixlo_f16: case aco_opcode::v_fma_mixhi_f16: /* VOP2 */ diff --git a/src/amd/compiler/aco_opcodes.py b/src/amd/compiler/aco_opcodes.py index f0af9b8c708..36b2d21e0a9 100644 --- a/src/amd/compiler/aco_opcodes.py +++ b/src/amd/compiler/aco_opcodes.py @@ -1205,6 +1205,7 @@ VOP3 = { ("v_interp_p1lv_f16", True, True, dst(1), src(1, M0, 1), op(gfx8=0x275, gfx10=0x343, gfx11=-1)), ("v_interp_p2_legacy_f16", True, True, dst(1), src(1, M0, 1), op(gfx8=0x276, gfx10=-1)), ("v_interp_p2_f16", True, True, dst(1), src(1, M0, 1), op(gfx9=0x277, gfx10=0x35a, gfx11=-1)), + ("v_interp_p2_hi_f16", True, True, dst(1), src(1, M0, 1), op(gfx9=0x277, gfx10=0x35a, gfx11=-1)), ("v_ldexp_f32", False, True, dst(1), src(1, 1), op(0x12b, gfx8=0x288, gfx10=0x362, gfx11=0x31c)), ("v_readlane_b32_e64", False, False, dst(1), src(1, 1), op(gfx8=0x289, gfx10=0x360)), ("v_writelane_b32_e64", False, False, dst(1), src(1, 1, 1), op(gfx8=0x28a, gfx10=0x361)), @@ -1862,6 +1863,9 @@ for ver in Opcode._fields: # v_mac_legacy_f32 is replaced with v_fmac_legacy_f32 on GFX10.3 if ver == 'gfx10' and names == set(['v_mac_legacy_f32', 'v_fmac_legacy_f32']): continue + # These are the same opcodes, but hi uses opsel + if names == set(['v_interp_p2_f16', 'v_interp_p2_hi_f16']): + continue print('%s and %s share the same opcode number (%s)' % (op_to_name[key], inst.name, ver)) sys.exit(1) diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index 6d1e05f36eb..3572f1a614f 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -623,6 +623,7 @@ can_apply_sgprs(opt_ctx& ctx, aco_ptr& instr) instr->opcode != aco_opcode::v_interp_p1lv_f16 && instr->opcode != aco_opcode::v_interp_p2_legacy_f16 && instr->opcode != aco_opcode::v_interp_p2_f16 && + instr->opcode != aco_opcode::v_interp_p2_hi_f16 && instr->opcode != aco_opcode::v_interp_p10_f32_inreg && instr->opcode != aco_opcode::v_interp_p2_f32_inreg && instr->opcode != aco_opcode::v_interp_p10_f16_f32_inreg && diff --git a/src/amd/compiler/aco_register_allocation.cpp b/src/amd/compiler/aco_register_allocation.cpp index 5a8c75a06e1..5cdc2639152 100644 --- a/src/amd/compiler/aco_register_allocation.cpp +++ b/src/amd/compiler/aco_register_allocation.cpp @@ -617,7 +617,7 @@ get_subdword_definition_info(Program* program, const aco_ptr& instr return std::make_pair(4, rc.size() * 4u); } - if (instr->isVALU() || instr->isVINTRP()) { + if (instr->isVALU()) { assert(rc.bytes() <= 2); if (can_use_SDWA(gfx_level, instr, false)) @@ -636,6 +636,7 @@ get_subdword_definition_info(Program* program, const aco_ptr& instr } switch (instr->opcode) { + case aco_opcode::v_interp_p2_f16: return std::make_pair(2u, 2u); /* D16 loads with _hi version */ case aco_opcode::ds_read_u8_d16: case aco_opcode::ds_read_i8_d16: @@ -715,6 +716,8 @@ add_subdword_definition(Program* program, aco_ptr& instr, PhysReg r if (reg.byte() == 0) return; + else if (instr->opcode == aco_opcode::v_interp_p2_f16) + instr->opcode = aco_opcode::v_interp_p2_hi_f16; else if (instr->opcode == aco_opcode::buffer_load_ubyte_d16) instr->opcode = aco_opcode::buffer_load_ubyte_d16_hi; else if (instr->opcode == aco_opcode::buffer_load_sbyte_d16) diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index 7baf1d12e86..fef1cf2c48e 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -195,7 +195,8 @@ validate_ir(Program* program) if (instr->opcode == aco_opcode::v_interp_p1ll_f16 || instr->opcode == aco_opcode::v_interp_p1lv_f16 || instr->opcode == aco_opcode::v_interp_p2_legacy_f16 || - instr->opcode == aco_opcode::v_interp_p2_f16) { + instr->opcode == aco_opcode::v_interp_p2_f16 || + instr->opcode == aco_opcode::v_interp_p2_hi_f16) { /* v_interp_*_fp16 are considered VINTRP by the compiler but * they are emitted as VOP3. */ @@ -1067,6 +1068,7 @@ validate_subdword_definition(amd_gfx_level gfx_level, const aco_ptr return true; switch (instr->opcode) { + case aco_opcode::v_interp_p2_hi_f16: case aco_opcode::v_fma_mixhi_f16: case aco_opcode::buffer_load_ubyte_d16_hi: case aco_opcode::buffer_load_sbyte_d16_hi: @@ -1094,7 +1096,7 @@ get_subdword_bytes_written(Program* program, const aco_ptr& instr, if (instr->isPseudo()) return gfx_level >= GFX8 ? def.bytes() : def.size() * 4u; - if (instr->isVALU()) { + if (instr->isVALU() || instr->isVINTRP()) { assert(def.bytes() <= 2); if (instr->isSDWA()) return instr->sdwa().dst_sel.size();