if (entry->src.stride * inst->src[arg].stride > 4)
return false;
+ /* Bail if the instruction type is larger than the execution type of the
+ * copy, what implies that each channel is reading multiple channels of the
+ * destination of the copy, and simply replacing the sources would give a
+ * program with different semantics.
+ */
+ if (type_sz(entry->dst.type) < type_sz(inst->src[arg].type))
+ return false;
+
/* Bail if the result of composing both strides cannot be expressed
* as another stride. This avoids, for example, trying to transform
* this:
switch (entry->src.file) {
case UNIFORM:
- assert(entry->src.width == 1);
case BAD_FILE:
case HW_REG:
- inst->src[arg].width = entry->src.width;
inst->src[arg].reg_offset = entry->src.reg_offset;
inst->src[arg].subreg_offset = entry->src.subreg_offset;
break;
case ATTR:
case GRF:
{
- assert(entry->src.width % inst->src[arg].width == 0);
/* In this case, we'll just leave the width alone. The source
* register could have different widths depending on how it is
* being used. For instance, if only half of the register was
case BRW_OPCODE_MACH:
case BRW_OPCODE_MUL:
+ case SHADER_OPCODE_MULH:
case BRW_OPCODE_ADD:
case BRW_OPCODE_OR:
case BRW_OPCODE_AND:
acp_entry *entry = ralloc(copy_prop_ctx, acp_entry);
entry->dst = inst->dst;
entry->dst.reg_offset = offset;
- entry->dst.width = effective_width;
entry->src = inst->src[i];
entry->regs_written = regs_written;
entry->opcode = inst->opcode;