From 15637334ceba7ad1ba8c46cb6a1446fb751e7599 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Sep 2024 17:59:24 -0700 Subject: [PATCH] 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 Part-of: --- .../compiler/brw_opt_copy_propagation.cpp | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/intel/compiler/brw_opt_copy_propagation.cpp b/src/intel/compiler/brw_opt_copy_propagation.cpp index dacc6ace38b..dd811e881c7 100644 --- a/src/intel/compiler/brw_opt_copy_propagation.cpp +++ b/src/intel/compiler/brw_opt_copy_propagation.cpp @@ -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));