From e8f5b9374b49688586f7467d698d6c3d396f77e1 Mon Sep 17 00:00:00 2001 From: Georg Lehmann Date: Sat, 14 Dec 2024 16:51:55 +0100 Subject: [PATCH] aco/optimizer: use new helpers to optimize mul(b2f(a), b) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foz-DB Navi48: Totals from 979 (1.19% of 82419) affected shaders: Instrs: 3630560 -> 3629463 (-0.03%); split: -0.03%, +0.00% CodeSize: 19154176 -> 19147124 (-0.04%); split: -0.04%, +0.00% Latency: 17700546 -> 17699505 (-0.01%); split: -0.01%, +0.01% InvThroughput: 3143808 -> 3143254 (-0.02%); split: -0.02%, +0.01% SClause: 76410 -> 76405 (-0.01%); split: -0.01%, +0.00% Copies: 256544 -> 256554 (+0.00%); split: -0.02%, +0.02% PreVGPRs: 40868 -> 40835 (-0.08%) VALU: 2003291 -> 2002466 (-0.04%); split: -0.04%, +0.00% SALU: 514000 -> 514006 (+0.00%) VOPD: 3254 -> 3256 (+0.06%); split: +0.12%, -0.06% Foz-DB Navi21: Totals from 926 (1.12% of 82387) affected shaders: MaxWaves: 21538 -> 21542 (+0.02%) Instrs: 2984216 -> 2983187 (-0.03%); split: -0.04%, +0.00% CodeSize: 16104112 -> 16097272 (-0.04%); split: -0.05%, +0.00% VGPRs: 46864 -> 46848 (-0.03%) Latency: 15678064 -> 15677099 (-0.01%); split: -0.01%, +0.00% InvThroughput: 3779550 -> 3778230 (-0.03%); split: -0.04%, +0.01% VClause: 81590 -> 81598 (+0.01%) SClause: 70753 -> 70751 (-0.00%); split: -0.01%, +0.00% Copies: 240446 -> 240466 (+0.01%); split: -0.01%, +0.02% PreSGPRs: 51121 -> 51062 (-0.12%) PreVGPRs: 38538 -> 38505 (-0.09%) VALU: 1978847 -> 1977777 (-0.05%); split: -0.06%, +0.00% SALU: 439184 -> 439212 (+0.01%) Reviewed-by: Daniel Schürmann Part-of: --- src/amd/compiler/aco_optimizer.cpp | 83 ++++++++++++----------- src/amd/compiler/tests/test_optimizer.cpp | 14 ++++ 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index 20cd0a59138..ae786481238 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -72,7 +72,6 @@ enum Label { label_clamp = 1ull << 36, label_insert = 1ull << 38, label_f2f16 = 1ull << 39, - label_b2f = 1ull << 40, label_b2i = 1ull << 41, }; @@ -83,8 +82,8 @@ static constexpr uint64_t input_mod_labels = label_abs_fp16 | label_abs_fp32_64 | label_neg_fp16 | label_neg_fp32_64; static constexpr uint64_t temp_labels = label_temp | label_uniform_bool | label_scc_invert | - label_b2f | label_b2i | input_mod_labels | - label_fcanonicalize_fp32_64 | label_fcanonicalize_fp16; + label_b2i | input_mod_labels | label_fcanonicalize_fp32_64 | + label_fcanonicalize_fp16; static constexpr uint64_t val_labels = label_constant | label_combined_instr; @@ -249,14 +248,6 @@ struct ssa_info { bool is_f2f16() { return label & label_f2f16; } - void set_b2f(Temp b2f_val) - { - add_label(label_b2f); - temp = b2f_val; - } - - bool is_b2f() { return label & label_b2f; } - void set_uniform_bitwise() { add_label(label_uniform_bitwise); } bool is_uniform_bitwise() { return label & label_uniform_bitwise; } @@ -2902,9 +2893,7 @@ label_instruction(opt_ctx& ctx, aco_ptr& instr) break; } case aco_opcode::v_cndmask_b32: - if (instr->operands[0].constantEquals(0) && instr->operands[1].constantEquals(0x3f800000u)) - ctx.info[instr->definitions[0].tempId()].set_b2f(instr->operands[2].getTemp()); - else if (instr->operands[0].constantEquals(0) && instr->operands[1].constantEquals(1)) + if (instr->operands[0].constantEquals(0) && instr->operands[1].constantEquals(1)) ctx.info[instr->definitions[0].tempId()].set_b2i(instr->operands[2].getTemp()); break; @@ -4637,6 +4626,39 @@ create_med3_cb(opt_ctx& ctx, alu_opt_info& info) return false; } +bool +check_constant(opt_ctx& ctx, alu_opt_info& info, unsigned idx, uint32_t expected) +{ + assert(idx < info.operands.size()); + aco_type type = {aco_base_type_uint, 1, 32}; /* maybe param in the future, if needed. */ + uint64_t constant; + return op_info_get_constant(ctx, info.operands[idx], type, &constant) && constant == expected; +} + +template +bool +check_const_cb(opt_ctx& ctx, alu_opt_info& info) +{ + return check_constant(ctx, info, idx, expected); +} + +template +bool +remove_const_cb(opt_ctx& ctx, alu_opt_info& info) +{ + if (!check_constant(ctx, info, info.operands.size() - 1, expected)) + return false; + info.operands.pop_back(); + return true; +} + +template +bool +and_cb(opt_ctx& ctx, alu_opt_info& info) +{ + return func1(ctx, info) && func2(ctx, info); +} + bool is_mul(Instruction* instr) { @@ -4749,32 +4771,6 @@ combine_instruction(opt_ctx& ctx, aco_ptr& instr) } if (instr->isSDWA()) { - /* v_mul_f32(v_cndmask_b32(0, 1.0, cond), a) -> v_cndmask_b32(0, a, cond) */ - } else if (((instr->opcode == aco_opcode::v_mul_f32 && !instr->definitions[0].isNaNPreserve() && - !instr->definitions[0].isInfPreserve()) || - (instr->opcode == aco_opcode::v_mul_legacy_f32 && - !instr->definitions[0].isSZPreserve())) && - !instr->usesModifiers() && !ctx.fp_mode.must_flush_denorms32) { - for (unsigned i = 0; i < 2; i++) { - if (instr->operands[i].isTemp() && ctx.info[instr->operands[i].tempId()].is_b2f() && - ctx.uses[instr->operands[i].tempId()] == 1 && instr->operands[!i].isTemp() && - instr->operands[!i].getTemp().type() == RegType::vgpr) { - ctx.uses[instr->operands[i].tempId()]--; - ctx.uses[ctx.info[instr->operands[i].tempId()].temp.id()]++; - - aco_ptr new_instr{ - create_instruction(aco_opcode::v_cndmask_b32, Format::VOP2, 3, 1)}; - new_instr->operands[0] = Operand::zero(); - new_instr->operands[1] = instr->operands[!i]; - new_instr->operands[2] = Operand(ctx.info[instr->operands[i].tempId()].temp); - new_instr->definitions[0] = instr->definitions[0]; - new_instr->pass_flags = instr->pass_flags; - instr = std::move(new_instr); - ctx.info[instr->definitions[0].tempId()].label = 0; - ctx.info[instr->definitions[0].tempId()].parent_instr = instr.get(); - return; - } - } } else if (instr->opcode == aco_opcode::v_or_b32 && ctx.program->gfx_level >= GFX9) { if (combine_three_valu_op(ctx, instr, aco_opcode::s_or_b32, aco_opcode::v_or3_b32, "012", 1 | 2)) { @@ -5005,6 +5001,13 @@ combine_instruction(opt_ctx& ctx, aco_ptr& instr) } else if (info.opcode == aco_opcode::v_min_i16_e64) { add_opt(v_min_i16_e64, v_min3_i16, 0x3, "120", nullptr, true); add_opt(v_max_i16_e64, v_med3_i16, 0x3, "012", create_med3_cb, true); + } else if (((info.opcode == aco_opcode::v_mul_f32 && !info.defs[0].isNaNPreserve() && + !info.defs[0].isInfPreserve()) || + (info.opcode == aco_opcode::v_mul_legacy_f32 && !info.defs[0].isSZPreserve())) && + !info.clamp && !info.omod && !ctx.fp_mode.must_flush_denorms32) { + /* v_mul_f32(a, v_cndmask_b32(0, 1.0, cond)) -> v_cndmask_b32(0, a, cond) */ + add_opt(v_cndmask_b32, v_cndmask_b32, 0x3, "1032", + and_cb, remove_const_cb<0x3f800000>>, true); } if (match_and_apply_patterns(ctx, info, patterns)) { diff --git a/src/amd/compiler/tests/test_optimizer.cpp b/src/amd/compiler/tests/test_optimizer.cpp index af3a33fefa3..06ddcd655f9 100644 --- a/src/amd/compiler/tests/test_optimizer.cpp +++ b/src/amd/compiler/tests/test_optimizer.cpp @@ -2185,3 +2185,17 @@ BEGIN_TEST(optimizer.fp64_clamp) finish_opt_test(); END_TEST + +BEGIN_TEST(optimizer.mul_b2f) + //>> v1: %a:v[0], s2: %b:s[0-1] = p_startpgm + if (!setup_cs("v1 s2", GFX11)) + return; + + //>> v1: %res0 = v_cndmask_b32 0, %a, %b + //! p_unit_test 0, %res0 + Temp cond = bld.vop2_e64(aco_opcode::v_cndmask_b32, bld.def(v1), Operand::c32(0), + Operand::c32(0x3F800000), inputs[1]); + writeout(0, bld.vop2(aco_opcode::v_mul_f32, bld.def(v1), inputs[0], cond)); + + finish_opt_test(); +END_TEST