+ /* Comparisons operate differently for ints and floats */
+ if (scan_inst->dst.type != inst->dst.type) {
+ /* Comparison result may be altered if the bit-size changes
+ * since that affects range, denorms, etc
+ */
+ if (type_sz(scan_inst->dst.type) != type_sz(inst->dst.type))
+ break;
+
+ /* We should propagate from a MOV to another instruction in a
+ * sequence like:
+ *
+ * and(16) g31<1>UD g20<8,8,1>UD g22<8,8,1>UD
+ * mov.nz.f0(16) null<1>F g31<8,8,1>D
+ */
+ if (inst->opcode == BRW_OPCODE_MOV) {
+ if ((inst->src[0].type != BRW_REGISTER_TYPE_D &&
+ inst->src[0].type != BRW_REGISTER_TYPE_UD) ||
+ (scan_inst->dst.type != BRW_REGISTER_TYPE_D &&
+ scan_inst->dst.type != BRW_REGISTER_TYPE_UD)) {
+ break;
+ }
+ } else if (brw_reg_type_is_floating_point(scan_inst->dst.type) !=
+ brw_reg_type_is_floating_point(inst->dst.type)) {
+ break;
+ }
+ }
+
+ /* 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.