intel/compiler: fix cmod propagation optimisations
Knowing following: - CMP writes to flag register the result of applying cmod to the `src0 - src1`. After that it stores the same value to dst. Other instructions first store their result to dst, and then store cmod(dst) to the flag register. - inst is either CMP or MOV - inst->dst is null - inst->src[0] overlaps with scan_inst->dst - inst->src[1] is zero - scan_inst wrote to a flag register There can be three possible paths: - scan_inst is CMP: Considering that src0 is either 0x0 (false), or 0xffffffff (true), and src1 is 0x0: - If inst's cmod is NZ, we can always remove scan_inst: NZ is invariant for false and true. This holds even if src0 is NaN: .nz is the only cmod, that returns true for NaN. - .g is invariant if src0 has a UD type - .l is invariant if src0 has a D type - scan_inst and inst have the same cmod: If scan_inst is anything than CMP, it already wrote the appropriate value to the flag register. - else: We can change cmod of scan_inst to that of inst, and remove inst. It is valid as long as we make sure that no instruction uses the flag register between scan_inst and inst. Nine new cmod_propagation unit tests: - cmp_cmpnz - cmp_cmpg - plnnz_cmpnz - plnnz_cmpz (*) - plnnz_sel_cmpz - cmp_cmpg_D - cmp_cmpg_UD (*) - cmp_cmpl_D (*) - cmp_cmpl_UD (*) this would fail without changes to brw_fs_cmod_propagation. This fixes optimisation that used to be illegal (see issue #2154) = Before = 0: linterp.z.f0.0(8) vgrf0:F, g2:F, attr0<0>:F 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f = After = 0: linterp.z.f0.0(8) vgrf0:F, g2:F, attr0<0>:F Now it is optimised as such (note change of cmod in line 0): = Before = 0: linterp.z.f0.0(8) vgrf0:F, g2:F, attr0<0>:F 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f = After = 0: linterp.nz.f0.0(8) vgrf0:F, g2:F, attr0<0>:F No shaderdb changes Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2154 Signed-off-by: Yevhenii Kolesnikov <yevhenii.kolesnikov@globallogic.com> Reviewed-by: Matt Turner <mattst88@gmail.com> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3348> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3348>
This commit is contained in:

committed by
Marge Bot

parent
3b76b3bc09
commit
32b7ba66b0
@@ -328,17 +328,69 @@ opt_cmod_propagation_local(const gen_device_info *devinfo, bblock_t *block)
|
||||
}
|
||||
}
|
||||
|
||||
/* If the instruction generating inst's source also wrote the
|
||||
* flag, and inst is doing a simple .nz comparison, then inst
|
||||
* is redundant - the appropriate value is already in the flag
|
||||
* register. Delete inst.
|
||||
/* Knowing following:
|
||||
* - CMP writes to flag register the result of
|
||||
* applying cmod to the `src0 - src1`.
|
||||
* After that it stores the same value to dst.
|
||||
* Other instructions first store their result to
|
||||
* dst, and then store cmod(dst) to the flag
|
||||
* register.
|
||||
* - inst is either CMP or MOV
|
||||
* - inst->dst is null
|
||||
* - inst->src[0] overlaps with scan_inst->dst
|
||||
* - inst->src[1] is zero
|
||||
* - scan_inst wrote to a flag register
|
||||
*
|
||||
* There can be three possible paths:
|
||||
*
|
||||
* - scan_inst is CMP:
|
||||
*
|
||||
* Considering that src0 is either 0x0 (false),
|
||||
* or 0xffffffff (true), and src1 is 0x0:
|
||||
*
|
||||
* - If inst's cmod is NZ, we can always remove
|
||||
* scan_inst: NZ is invariant for false and true. This
|
||||
* holds even if src0 is NaN: .nz is the only cmod,
|
||||
* that returns true for NaN.
|
||||
*
|
||||
* - .g is invariant if src0 has a UD type
|
||||
*
|
||||
* - .l is invariant if src0 has a D type
|
||||
*
|
||||
* - scan_inst and inst have the same cmod:
|
||||
*
|
||||
* If scan_inst is anything than CMP, it already
|
||||
* wrote the appropriate value to the flag register.
|
||||
*
|
||||
* - else:
|
||||
*
|
||||
* We can change cmod of scan_inst to that of inst,
|
||||
* and remove inst. It is valid as long as we make
|
||||
* sure that no instruction uses the flag register
|
||||
* between scan_inst and inst.
|
||||
*/
|
||||
if (inst->conditional_mod == BRW_CONDITIONAL_NZ &&
|
||||
!inst->src[0].negate &&
|
||||
if (!inst->src[0].negate &&
|
||||
scan_inst->flags_written()) {
|
||||
inst->remove(block);
|
||||
progress = true;
|
||||
break;
|
||||
if (scan_inst->opcode == BRW_OPCODE_CMP) {
|
||||
if ((inst->conditional_mod == BRW_CONDITIONAL_NZ) ||
|
||||
(inst->conditional_mod == BRW_CONDITIONAL_G &&
|
||||
inst->src[0].type == BRW_REGISTER_TYPE_UD) ||
|
||||
(inst->conditional_mod == BRW_CONDITIONAL_L &&
|
||||
inst->src[0].type == BRW_REGISTER_TYPE_D)) {
|
||||
inst->remove(block);
|
||||
progress = true;
|
||||
break;
|
||||
}
|
||||
} else if (scan_inst->conditional_mod == inst->conditional_mod) {
|
||||
inst->remove(block);
|
||||
progress = true;
|
||||
break;
|
||||
} else if (!read_flag) {
|
||||
scan_inst->conditional_mod = inst->conditional_mod;
|
||||
inst->remove(block);
|
||||
progress = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The conditional mod of the CMP/CMPN instructions behaves
|
||||
|
Reference in New Issue
Block a user