intel/fs: Add fast path for ballot(true)

This doesn't help very much now. A later commit adds a NIR optimization
pass, tentatively called nir_opt_uniform_subgroup, that converts many
kinds of subgroup operations to things involving
bitCount(ballot(true)). This commit makes a huge difference in the
results of that later commit.

No shader-db changes on any Intel platform.

Fossil-db results:

All Intel platforms had similar results. (Ice Lake shown)
Totals:
Instrs: 165558033 -> 165557519 (-0.00%)
Cycles: 15156188362 -> 15156178922 (-0.00%); split: -0.00%, +0.00%

Totals from 299 (0.05% of 656117) affected shaders:
Instrs: 88293 -> 87779 (-0.58%)
Cycles: 3709498 -> 3700058 (-0.25%); split: -0.28%, +0.03%

v2: Rebase on splitting ELK from BRW. Remove devinfo->ver >= 8 check.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27044>
This commit is contained in:
Ian Romanick
2024-01-05 09:19:38 -08:00
parent c42830c64a
commit 8fb37ef985
8 changed files with 49 additions and 10 deletions
+8
View File
@@ -489,6 +489,14 @@ enum opcode {
*/
SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL,
/**
* Return the current execution mask and assign it to the first component
* of the destination.
*
* \sa opcode::FS_OPCODE_LOAD_LIVE_CHANNELS
*/
SHADER_OPCODE_LOAD_LIVE_CHANNELS,
/**
* Return the current execution mask in the specified flag subregister.
* Can be CSE'ed more easily than a plain MOV from the ce0 ARF register.
+1
View File
@@ -78,6 +78,7 @@ is_expression(const fs_visitor *v, const fs_inst *const inst)
case FS_OPCODE_LINTERP:
case SHADER_OPCODE_FIND_LIVE_CHANNEL:
case SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL:
case SHADER_OPCODE_LOAD_LIVE_CHANNELS:
case FS_OPCODE_LOAD_LIVE_CHANNELS:
case SHADER_OPCODE_BROADCAST:
case SHADER_OPCODE_MOV_INDIRECT:
+4
View File
@@ -2269,6 +2269,10 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width,
brw_find_live_channel(p, dst, true);
break;
case SHADER_OPCODE_LOAD_LIVE_CHANNELS:
unreachable("Should be lowered by lower_find_live_channel()");
break;
case FS_OPCODE_LOAD_LIVE_CHANNELS: {
assert(devinfo->ver >= 8);
assert(inst->force_writemask_all && inst->group == 0);
+16 -3
View File
@@ -473,7 +473,8 @@ brw_fs_lower_find_live_channel(fs_visitor &s)
foreach_block_and_inst_safe(block, fs_inst, inst, s.cfg) {
if (inst->opcode != SHADER_OPCODE_FIND_LIVE_CHANNEL &&
inst->opcode != SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL)
inst->opcode != SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL &&
inst->opcode != SHADER_OPCODE_LOAD_LIVE_CHANNELS)
continue;
bool first = inst->opcode == SHADER_OPCODE_FIND_LIVE_CHANNEL;
@@ -515,13 +516,25 @@ brw_fs_lower_find_live_channel(fs_visitor &s)
exec_mask = mask;
}
if (first) {
switch (inst->opcode) {
case SHADER_OPCODE_FIND_LIVE_CHANNEL:
ubld.FBL(inst->dst, exec_mask);
} else {
break;
case SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL: {
fs_reg tmp = ubld.vgrf(BRW_REGISTER_TYPE_UD, 1);
ubld.UNDEF(tmp);
ubld.LZD(tmp, exec_mask);
ubld.ADD(inst->dst, negate(tmp), brw_imm_uw(31));
break;
}
case SHADER_OPCODE_LOAD_LIVE_CHANNELS:
ubld.MOV(inst->dst, exec_mask);
break;
default:
unreachable("Impossible.");
}
inst->remove(block);
+15 -6
View File
@@ -7282,6 +7282,21 @@ fs_nir_emit_intrinsic(nir_to_brw_state &ntb,
}
case nir_intrinsic_ballot: {
if (instr->def.bit_size > 32) {
dest.type = BRW_REGISTER_TYPE_UQ;
} else {
dest.type = BRW_REGISTER_TYPE_UD;
}
/* Implement a fast-path for ballot(true). */
if (nir_src_is_const(instr->src[0]) &&
nir_src_as_bool(instr->src[0])) {
fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD);
bld.exec_all().emit(SHADER_OPCODE_LOAD_LIVE_CHANNELS, tmp);
bld.MOV(dest, fs_reg(component(tmp, 0)));
break;
}
const fs_reg value = retype(get_nir_src(ntb, instr->src[0]),
BRW_REGISTER_TYPE_UD);
struct brw_reg flag = brw_flag_reg(0, 0);
@@ -7291,12 +7306,6 @@ fs_nir_emit_intrinsic(nir_to_brw_state &ntb,
bld.exec_all().group(1, 0).MOV(flag, retype(brw_imm_ud(0u), flag.type));
bld.CMP(bld.null_reg_ud(), value, brw_imm_ud(0u), BRW_CONDITIONAL_NZ);
if (instr->def.bit_size > 32) {
dest.type = BRW_REGISTER_TYPE_UQ;
} else {
dest.type = BRW_REGISTER_TYPE_UD;
}
bld.MOV(dest, flag);
break;
}
@@ -723,6 +723,7 @@ namespace {
case SHADER_OPCODE_FIND_LIVE_CHANNEL:
case SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL:
case SHADER_OPCODE_LOAD_LIVE_CHANNELS:
if (devinfo->ver >= 11)
return calculate_desc(info, EU_UNIT_FPU, 2, 0, 0, 2, 0,
0, 10, 6 /* XXX */, 14 /* XXX */, 0, 0);
@@ -1176,6 +1176,7 @@ has_cross_lane_access(const fs_inst *inst)
inst->opcode == SHADER_OPCODE_CLUSTER_BROADCAST ||
inst->opcode == SHADER_OPCODE_SHUFFLE ||
inst->opcode == FS_OPCODE_LOAD_LIVE_CHANNELS ||
inst->opcode == SHADER_OPCODE_LOAD_LIVE_CHANNELS ||
inst->opcode == SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL ||
inst->opcode == SHADER_OPCODE_FIND_LIVE_CHANNEL)
return true;
+3 -1
View File
@@ -376,8 +376,10 @@ brw_instruction_name(const struct brw_isa_info *isa, enum opcode op)
return "find_live_channel";
case SHADER_OPCODE_FIND_LAST_LIVE_CHANNEL:
return "find_last_live_channel";
case FS_OPCODE_LOAD_LIVE_CHANNELS:
case SHADER_OPCODE_LOAD_LIVE_CHANNELS:
return "load_live_channels";
case FS_OPCODE_LOAD_LIVE_CHANNELS:
return "fs_load_live_channels";
case SHADER_OPCODE_BROADCAST:
return "broadcast";