diff --git a/src/intel/compiler/brw_opt_register_coalesce.cpp b/src/intel/compiler/brw_opt_register_coalesce.cpp index eb9e3a2baf2..19fcd122a27 100644 --- a/src/intel/compiler/brw_opt_register_coalesce.cpp +++ b/src/intel/compiler/brw_opt_register_coalesce.cpp @@ -240,6 +240,7 @@ brw_opt_register_coalesce(brw_shader &s) brw_inst **mov = new brw_inst *[MAX_VGRF_SIZE(devinfo)]; int *dst_var = new int[MAX_VGRF_SIZE(devinfo)]; int *src_var = new int[MAX_VGRF_SIZE(devinfo)]; + const brw_def_analysis &defs = s.def_analysis.require(); foreach_block_and_inst(block, brw_inst, inst, s.cfg) { if (!is_coalesce_candidate(&s, inst)) @@ -251,6 +252,20 @@ brw_opt_register_coalesce(brw_shader &s) continue; } + /* Do not allow register coalescing of a value that was generated by a + * LOAD_REG. Register coalesce works by making the destination of the + * original instruction (in this case the LOAD_REG) be the same as the + * destination of the MOV. + * + * If the MOV result is not a def (due to multiple writes or being used + * outside the body of a loop), this will cause the LOAD_REG to also not + * be a def. That violates the requirement of the LOAD_REG, and it will + * fail validation. + */ + const brw_inst *const def = defs.get(inst->src[0]); + if (def && def->opcode == SHADER_OPCODE_LOAD_REG) + continue; + if (src_reg != inst->src[0].nr) { src_reg = inst->src[0].nr;