ir_to_mesa: Do not emit OPCODE_SEQ or OPCODE_SNE
Nothing that consumes the output of this backend consumes them navtively. This is *not* the way i915 has implemented these instructions, but, as far as I am able to tell, this is the way both the Cg compiler and the HLSL compiler implement these operations. Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com>
This commit is contained in:
@@ -304,6 +304,22 @@ public:
|
||||
|
||||
void emit_swz(ir_expression *ir);
|
||||
|
||||
void emit_equality_comparison(ir_expression *ir, enum prog_opcode op,
|
||||
dst_reg dst,
|
||||
const src_reg &src0, const src_reg &src1);
|
||||
|
||||
inline void emit_sne(ir_expression *ir, dst_reg dst,
|
||||
const src_reg &src0, const src_reg &src1)
|
||||
{
|
||||
emit_equality_comparison(ir, OPCODE_SLT, dst, src0, src1);
|
||||
}
|
||||
|
||||
inline void emit_seq(ir_expression *ir, dst_reg dst,
|
||||
const src_reg &src0, const src_reg &src1)
|
||||
{
|
||||
emit_equality_comparison(ir, OPCODE_SGE, dst, src0, src1);
|
||||
}
|
||||
|
||||
bool process_move_condition(ir_rvalue *ir);
|
||||
|
||||
void copy_propagate(void);
|
||||
@@ -912,6 +928,46 @@ ir_to_mesa_visitor::emit_swz(ir_expression *ir)
|
||||
this->result = result_src;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
{
|
||||
@@ -1086,17 +1142,17 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
emit(ir, OPCODE_SGE, result_dst, op[0], op[1]);
|
||||
break;
|
||||
case ir_binop_equal:
|
||||
emit(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
|
||||
emit_seq(ir, result_dst, op[0], op[1]);
|
||||
break;
|
||||
case ir_binop_nequal:
|
||||
emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
|
||||
emit_sne(ir, result_dst, op[0], op[1]);
|
||||
break;
|
||||
case ir_binop_all_equal:
|
||||
/* "==" operator producing a scalar boolean. */
|
||||
if (ir->operands[0]->type->is_vector() ||
|
||||
ir->operands[1]->type->is_vector()) {
|
||||
src_reg temp = get_temp(glsl_type::vec4_type);
|
||||
emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]);
|
||||
emit_sne(ir, dst_reg(temp), op[0], op[1]);
|
||||
|
||||
/* After the dot-product, the value will be an integer on the
|
||||
* range [0,4]. Zero becomes 1.0, and positive values become zero.
|
||||
@@ -1111,7 +1167,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
sge_src.negate = ~sge_src.negate;
|
||||
emit(ir, OPCODE_SGE, result_dst, sge_src, src_reg_for_float(0.0));
|
||||
} else {
|
||||
emit(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
|
||||
emit_seq(ir, result_dst, op[0], op[1]);
|
||||
}
|
||||
break;
|
||||
case ir_binop_any_nequal:
|
||||
@@ -1124,7 +1180,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
ir->operands[1]->as_constant()->is_zero()) {
|
||||
temp = op[0];
|
||||
} else {
|
||||
emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]);
|
||||
emit_sne(ir, dst_reg(temp), op[0], op[1]);
|
||||
}
|
||||
|
||||
/* After the dot-product, the value will be an integer on the
|
||||
@@ -1147,12 +1203,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0));
|
||||
}
|
||||
} else {
|
||||
emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
|
||||
emit_sne(ir, result_dst, op[0], op[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case ir_binop_logic_xor:
|
||||
emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
|
||||
emit_sne(ir, result_dst, op[0], op[1]);
|
||||
break;
|
||||
|
||||
case ir_binop_logic_or: {
|
||||
@@ -1217,8 +1273,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
break;
|
||||
case ir_unop_f2b:
|
||||
case ir_unop_i2b:
|
||||
emit(ir, OPCODE_SNE, result_dst,
|
||||
op[0], src_reg_for_float(0.0));
|
||||
emit_sne(ir, result_dst, op[0], src_reg_for_float(0.0));
|
||||
break;
|
||||
case ir_unop_bitcast_f2i: // Ignore these 4, they can't happen here anyway
|
||||
case ir_unop_bitcast_f2u:
|
||||
|
Reference in New Issue
Block a user