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:
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user