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 <mattst88@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37186>
This commit is contained in:
Ian Romanick 2025-06-12 09:55:29 -07:00 committed by Marge Bot
parent fb193ac190
commit 4193895145
5 changed files with 174 additions and 6 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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);
}