brw/copy: Prepare copy_propagation for load_reg

The changes to try_copy_propagate will be removed later in the series.

v2: Fix up some comments to note that offset != 0 is allowed only when
stride == 0. Apply same offset=0 restriction in try_copy_propagate_def
too. Allow copy propagation if the source is either a def or
UNIFORM. Don't copy prop a load_reg through a non-def value.

Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31497>
This commit is contained in:
Ian Romanick
2024-09-24 17:59:24 -07:00
committed by Marge Bot
parent cfc50390fb
commit 15637334ce
@@ -660,13 +660,25 @@ instruction_requires_packed_data(brw_inst *inst)
}
static bool
try_copy_propagate(brw_shader &s, brw_inst *inst,
try_copy_propagate(brw_shader &s, const brw_def_analysis &defs, brw_inst *inst,
acp_entry *entry, int arg,
uint8_t max_polygons)
{
if (inst->src[arg].file != VGRF)
return false;
/* Do not copy propage a load_reg value to a different block through a
* non-def. This can occur when `entry` is the loop counter, and `inst` is
* a use of the loop counter outside the loop. If the use outside the loop
* is replaced with the def from the load_reg, def analysis will later
* determine that the load_reg does not produce a def.
*/
const brw_inst *const def = defs.get(entry->src);
if (def != NULL && def->opcode == SHADER_OPCODE_LOAD_REG &&
def->block != inst->block) {
return false;
}
const struct intel_device_info *devinfo = s.devinfo;
assert(entry->src.file == VGRF || entry->src.file == UNIFORM ||
@@ -758,6 +770,16 @@ try_copy_propagate(brw_shader &s, brw_inst *inst,
if (instruction_requires_packed_data(inst) && entry_stride != 1)
return false;
/* load_reg loads a whole VGRF into a def. It is not allowed for the source
* to have a stride or a non-zero offset (unless stride == 0). It is
* allowed for the source to to be uniform.
*/
if (inst->opcode == SHADER_OPCODE_LOAD_REG &&
!is_uniform(entry->src) &&
(entry->src.offset != 0 || entry_stride > 1)) {
return false;
}
const brw_reg_type dst_type = (has_source_modifiers &&
entry->dst.type != inst->src[arg].type) ?
entry->dst.type : inst->dst.type;
@@ -1379,6 +1401,7 @@ opt_copy_propagation_local(brw_shader &s, linear_ctx *lin_ctx,
uint8_t max_polygons)
{
const struct intel_device_info *devinfo = s.devinfo;
const brw_def_analysis &defs = s.def_analysis.require();
bool progress = false;
foreach_inst_in_block(brw_inst, inst, block) {
@@ -1397,7 +1420,7 @@ opt_copy_propagation_local(brw_shader &s, linear_ctx *lin_ctx,
break;
}
} else {
if (try_copy_propagate(s, inst, *iter, i, max_polygons)) {
if (try_copy_propagate(s, defs, inst, *iter, i, max_polygons)) {
progress = true;
break;
}
@@ -1638,6 +1661,16 @@ try_copy_propagate_def(brw_shader &s,
if (instruction_requires_packed_data(inst) && entry_stride != 1)
return false;
/* load_reg loads a whole VGRF into a def. It is not allowed for the source
* to have a stride or a non-zero offset (unless stride == 0). It is
* allowed for the source to to be uniform.
*/
if (inst->opcode == SHADER_OPCODE_LOAD_REG &&
!is_uniform(val) &&
(val.offset != 0 || entry_stride > 1)) {
return false;
}
const brw_reg_type dst_type = (has_source_modifiers &&
def->dst.type != inst->src[arg].type) ?
def->dst.type : inst->dst.type;
@@ -1845,6 +1878,21 @@ find_value_for_offset(brw_inst *def, const brw_reg &src, unsigned src_size)
}
break;
}
case SHADER_OPCODE_LOAD_REG: {
val = def->src[0];
unsigned rel_offset = src.offset - def->dst.offset;
if (val.stride == 0)
rel_offset %= brw_type_size_bytes(def->dst.type);
if (val.file == IMM)
val = extract_imm(val, src.type, rel_offset);
else
val = byte_offset(def->src[0], rel_offset);
break;
}
default:
break;
}
@@ -1890,6 +1938,15 @@ brw_opt_copy_propagation_defs(brw_shader &s)
}
}
/* Only propagate through a load_reg if the source is a def or a
* UNIFORM (since these are also always invariant). The destination
* of a load_reg is always a def (by definition).
*/
if (def->opcode == SHADER_OPCODE_LOAD_REG &&
(defs.get(def->src[0]) == NULL && def->src[0].file != UNIFORM)) {
continue;
}
brw_reg val =
find_value_for_offset(def, inst->src[i], inst->size_read(s.devinfo, i));