From 4193895145b4b6b2e06b0d2a2fc99296c4694d28 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 12 Jun 2025 09:55:29 -0700 Subject: [PATCH] brw/cmod: Enable limited cmod propagation for BFN cmod propagation needs more work. Since the result type is always UD, BRW_CONDITION_G should be able to substitute for NZ. Either that or users of the condition could be rewritten to use an inverted condition. v2: Add a couple more unit tests. Suggested by Matt. Reviewed-by: Matt Turner Part-of: --- src/intel/compiler/brw/brw_from_nir.cpp | 2 +- src/intel/compiler/brw/brw_inst.cpp | 11 +- src/intel/compiler/brw/brw_inst.h | 2 +- .../compiler/brw/brw_opt_cmod_propagation.cpp | 17 +- .../brw/test_opt_cmod_propagation.cpp | 148 ++++++++++++++++++ 5 files changed, 174 insertions(+), 6 deletions(-) diff --git a/src/intel/compiler/brw/brw_from_nir.cpp b/src/intel/compiler/brw/brw_from_nir.cpp index b433fa7c2e0..fd69d1eb0e1 100644 --- a/src/intel/compiler/brw/brw_from_nir.cpp +++ b/src/intel/compiler/brw/brw_from_nir.cpp @@ -4231,7 +4231,7 @@ brw_from_nir_emit_fs_intrinsic(nir_to_brw_state &ntb, cmp = (brw_inst *) s.instructions.get_tail(); if (cmp->conditional_mod == BRW_CONDITIONAL_NONE) { - if (cmp->can_do_cmod()) + if (cmp->can_do_cmod(BRW_CONDITIONAL_Z)) cmp->conditional_mod = BRW_CONDITIONAL_Z; else cmp = NULL; diff --git a/src/intel/compiler/brw/brw_inst.cpp b/src/intel/compiler/brw/brw_inst.cpp index b26b537f3d9..a6bf9b2083f 100644 --- a/src/intel/compiler/brw/brw_inst.cpp +++ b/src/intel/compiler/brw/brw_inst.cpp @@ -370,7 +370,7 @@ brw_inst::can_do_source_mods(const struct intel_device_info *devinfo) const } bool -brw_inst::can_do_cmod() const +brw_inst::can_do_cmod(enum brw_conditional_mod cmod) const { switch (opcode) { case BRW_OPCODE_ADD: @@ -406,6 +406,15 @@ brw_inst::can_do_cmod() const case BRW_OPCODE_SUBB: case BRW_OPCODE_XOR: break; + + case BRW_OPCODE_BFN: + if (cmod != BRW_CONDITIONAL_Z && + cmod != BRW_CONDITIONAL_G && + cmod != BRW_CONDITIONAL_L) + return false; + + break; + default: return false; } diff --git a/src/intel/compiler/brw/brw_inst.h b/src/intel/compiler/brw/brw_inst.h index 6ad4d786ea8..ba553d6393f 100644 --- a/src/intel/compiler/brw/brw_inst.h +++ b/src/intel/compiler/brw/brw_inst.h @@ -90,7 +90,7 @@ struct brw_inst : brw_exec_node { unsigned components_read(unsigned i) const; unsigned size_read(const struct intel_device_info *devinfo, int arg) const; bool can_do_source_mods(const struct intel_device_info *devinfo) const; - bool can_do_cmod() const; + bool can_do_cmod(enum brw_conditional_mod cmod) const; bool can_change_types() const; bool has_source_and_destination_hazard() const; diff --git a/src/intel/compiler/brw/brw_opt_cmod_propagation.cpp b/src/intel/compiler/brw/brw_opt_cmod_propagation.cpp index b2b02c0b8f4..bff63e73047 100644 --- a/src/intel/compiler/brw/brw_opt_cmod_propagation.cpp +++ b/src/intel/compiler/brw/brw_opt_cmod_propagation.cpp @@ -210,7 +210,7 @@ cmod_propagate_cmp_to_add(const intel_device_info *devinfo, brw_inst *inst) } /* Otherwise, try propagating the conditional. */ - if (scan_inst->can_do_cmod() && + if (scan_inst->can_do_cmod(cond) && ((!read_flag && scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) || scan_inst->conditional_mod == cond)) { scan_inst->conditional_mod = cond; @@ -464,7 +464,8 @@ opt_cmod_propagation_local(const intel_device_info *devinfo, bblock_t *block) inst->remove(); progress = true; break; - } else if (!read_flag && scan_inst->can_do_cmod()) { + } else if (!read_flag && + scan_inst->can_do_cmod(inst->conditional_mod)) { scan_inst->conditional_mod = inst->conditional_mod; scan_inst->flag_subreg = inst->flag_subreg; inst->remove(); @@ -506,6 +507,16 @@ opt_cmod_propagation_local(const intel_device_info *devinfo, bblock_t *block) inst->src[0].negate ? brw_swap_cmod(inst->conditional_mod) : inst->conditional_mod; + /* BFN supports a limited subset of possible conditions. It + * notably lacks NZ. However, if the destination is unsigned, G + * and NZ are equivalent. + */ + if (scan_inst->opcode == BRW_OPCODE_BFN && + brw_type_is_uint(scan_inst->dst.type) && + cond == BRW_CONDITIONAL_NZ) { + cond = BRW_CONDITIONAL_G; + } + /* From the Kaby Lake PRM Vol. 7 "Assigning Conditional Flags": * * * Note that the [post condition signal] bits generated at @@ -524,7 +535,7 @@ opt_cmod_propagation_local(const intel_device_info *devinfo, bblock_t *block) */ /* Otherwise, try propagating the conditional. */ - if (scan_inst->can_do_cmod() && + if (scan_inst->can_do_cmod(cond) && ((!read_flag && scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) || scan_inst->conditional_mod == cond)) { scan_inst->conditional_mod = cond; diff --git a/src/intel/compiler/brw/test_opt_cmod_propagation.cpp b/src/intel/compiler/brw/test_opt_cmod_propagation.cpp index 84f28f56b96..3c9b5edc69f 100644 --- a/src/intel/compiler/brw/test_opt_cmod_propagation.cpp +++ b/src/intel/compiler/brw/test_opt_cmod_propagation.cpp @@ -2467,3 +2467,151 @@ TEST_F(cmod_propagation_test, Boolean_size_conversion) EXPECT_SHADERS_MATCH(bld, exp); } + +TEST_F(cmod_propagation_test, BFN_CMP_Z) +{ + // BFN doesn't exist on earlier platforms. + set_gfx_verx10(125); + + brw_builder bld = make_shader(); + brw_builder exp = make_shader(); + + brw_reg dest1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src0 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src2 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg zero = brw_imm_ud(0); + + bld.BFN(dest1, src0, src1, src2, 0xfe); + bld.CMP(bld.null_reg_d(), dest1, zero, BRW_CONDITIONAL_Z); + + EXPECT_PROGRESS(brw_opt_cmod_propagation, bld); + + exp.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_Z; + + EXPECT_SHADERS_MATCH(bld, exp); +} + +TEST_F(cmod_propagation_test, BFN_Z_CMP_Z) +{ + // BFN doesn't exist on earlier platforms. + set_gfx_verx10(125); + + brw_builder bld = make_shader(); + brw_builder exp = make_shader(); + + brw_reg dest1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src0 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src2 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg zero = brw_imm_ud(0); + + bld.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_Z; + bld.CMP(bld.null_reg_d(), dest1, zero, BRW_CONDITIONAL_Z); + + EXPECT_PROGRESS(brw_opt_cmod_propagation, bld); + + exp.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_Z; + + EXPECT_SHADERS_MATCH(bld, exp); +} + +TEST_F(cmod_propagation_test, BFN_CMP_NZ) +{ + // BFN doesn't exist on earlier platforms. + set_gfx_verx10(125); + + brw_builder bld = make_shader(); + brw_builder exp = make_shader(); + + brw_reg dest1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src0 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src2 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg zero = brw_imm_ud(0); + + bld.BFN(dest1, src0, src1, src2, 0xfe); + bld.CMP(bld.null_reg_d(), dest1, zero, BRW_CONDITIONAL_NZ); + + EXPECT_PROGRESS(brw_opt_cmod_propagation, bld); + + exp.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_G; + + EXPECT_SHADERS_MATCH(bld, exp); +} + +TEST_F(cmod_propagation_test, BFN_CMP_D_NZ) +{ + // BFN doesn't exist on earlier platforms. + set_gfx_verx10(125); + + brw_builder bld = make_shader(); + brw_builder exp = make_shader(); + + brw_reg dest1 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg src0 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg src1 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg src2 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg zero = brw_imm_ud(0); + + bld.BFN(dest1, src0, src1, src2, 0xfe); + bld.CMP(bld.null_reg_d(), dest1, zero, BRW_CONDITIONAL_NZ); + + EXPECT_NO_PROGRESS(brw_opt_cmod_propagation, bld); +} + +TEST_F(cmod_propagation_test, BFN_G_CMP_NZ) +{ + // BFN doesn't exist on earlier platforms. + set_gfx_verx10(125); + + brw_builder bld = make_shader(); + brw_builder exp = make_shader(); + + brw_reg dest1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src0 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src2 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg zero = brw_imm_ud(0); + + bld.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_G; + bld.CMP(bld.null_reg_d(), dest1, zero, BRW_CONDITIONAL_NZ); + + EXPECT_PROGRESS(brw_opt_cmod_propagation, bld); + + exp.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_G; + + EXPECT_SHADERS_MATCH(bld, exp); +} + +TEST_F(cmod_propagation_test, BFN_G_CMP_D_G) +{ + // BFN doesn't exist on earlier platforms. + set_gfx_verx10(125); + + brw_builder bld = make_shader(); + brw_builder exp = make_shader(); + + brw_reg dest1 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg src0 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg src1 = vgrf(bld, exp, BRW_TYPE_UD); + brw_reg src2 = vgrf(bld, exp, BRW_TYPE_D); + brw_reg zero = brw_imm_ud(0); + + bld.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_G; + bld.CMP(bld.null_reg_d(), dest1, zero, BRW_CONDITIONAL_G); + + EXPECT_PROGRESS(brw_opt_cmod_propagation, bld); + + exp.BFN(dest1, src0, src1, src2, 0xfe) + ->conditional_mod = BRW_CONDITIONAL_G; + + EXPECT_SHADERS_MATCH(bld, exp); +}