+void
+ir_to_mesa_visitor::emit_equality_comparison(ir_expression *ir,
+ enum prog_opcode op,
+ dst_reg dst,
+ const src_reg &src0,
+ const src_reg &src1)
+{
+ src_reg difference;
+ src_reg abs_difference = get_temp(glsl_type::vec4_type);
+ const src_reg zero = src_reg_for_float(0.0);
+
+ /* x == y is equivalent to -abs(x-y) >= 0. Since all of the code that
+ * consumes the generated IR is pretty dumb, take special care when one
+ * of the operands is zero.
+ *
+ * Similarly, x != y is equivalent to -abs(x-y) < 0.
+ */
+ if (src0.file == zero.file &&
+ src0.index == zero.index &&
+ src0.swizzle == zero.swizzle) {
+ difference = src1;
+ } else if (src1.file == zero.file &&
+ src1.index == zero.index &&
+ src1.swizzle == zero.swizzle) {
+ difference = src0;
+ } else {
+ difference = get_temp(glsl_type::vec4_type);
+
+ src_reg tmp_src = src0;
+ tmp_src.negate = ~tmp_src.negate;
+
+ emit(ir, OPCODE_ADD, dst_reg(difference), tmp_src, src1);
+ }
+
+ emit(ir, OPCODE_ABS, dst_reg(abs_difference), difference);
+
+ abs_difference.negate = ~abs_difference.negate;
+ emit(ir, op, dst, abs_difference, zero);
+}
+