diff options
author | Matt Turner <[email protected]> | 2014-12-02 12:28:13 -0800 |
---|---|---|
committer | Matt Turner <[email protected]> | 2014-12-05 09:49:42 -0800 |
commit | 2881b123d00562fee8b7d2b4f7825f89a73e0d9f (patch) | |
tree | e89036c38d6dcd5a89858711319a1a91fb0041ca /src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | |
parent | 05e2578cac608ba703d188fdff4903b92dec4aed (diff) |
i965: Use ~0 to represent true on all generations.
Jason realized that we could fix the result of the CMP instruction on
Gen <= 5 by doing -(result & 1). Also do the resolves in the vec4
backend before use, rather than when the bool was created. The FS does
this and it saves some unnecessary resolves.
On Ironlake:
total instructions in shared programs: 4289762 -> 4287277 (-0.06%)
instructions in affected programs: 619430 -> 616945 (-0.40%)
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 124 |
1 files changed, 77 insertions, 47 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index a2c05eda14d..73fff751dfb 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -819,18 +819,36 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, break; case ir_binop_logic_xor: - inst = emit(XOR(dst_null_d(), op[0], op[1])); - inst->conditional_mod = BRW_CONDITIONAL_NZ; + if (brw->gen <= 5) { + src_reg temp = src_reg(this, ir->type); + emit(XOR(dst_reg(temp), op[0], op[1])); + inst = emit(AND(dst_null_d(), temp, src_reg(1))); + } else { + inst = emit(XOR(dst_null_d(), op[0], op[1])); + } + inst->conditional_mod = BRW_CONDITIONAL_NZ; break; case ir_binop_logic_or: - inst = emit(OR(dst_null_d(), op[0], op[1])); - inst->conditional_mod = BRW_CONDITIONAL_NZ; + if (brw->gen <= 5) { + src_reg temp = src_reg(this, ir->type); + emit(OR(dst_reg(temp), op[0], op[1])); + inst = emit(AND(dst_null_d(), temp, src_reg(1))); + } else { + inst = emit(OR(dst_null_d(), op[0], op[1])); + } + inst->conditional_mod = BRW_CONDITIONAL_NZ; break; case ir_binop_logic_and: - inst = emit(AND(dst_null_d(), op[0], op[1])); - inst->conditional_mod = BRW_CONDITIONAL_NZ; + if (brw->gen <= 5) { + src_reg temp = src_reg(this, ir->type); + emit(AND(dst_reg(temp), op[0], op[1])); + inst = emit(AND(dst_null_d(), temp, src_reg(1))); + } else { + inst = emit(AND(dst_null_d(), op[0], op[1])); + } + inst->conditional_mod = BRW_CONDITIONAL_NZ; break; case ir_unop_f2b: @@ -852,16 +870,27 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, break; case ir_binop_all_equal: + if (brw->gen <= 5) { + resolve_bool_comparison(expr->operands[0], &op[0]); + resolve_bool_comparison(expr->operands[1], &op[1]); + } inst = emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_Z)); *predicate = BRW_PREDICATE_ALIGN16_ALL4H; break; case ir_binop_any_nequal: + if (brw->gen <= 5) { + resolve_bool_comparison(expr->operands[0], &op[0]); + resolve_bool_comparison(expr->operands[1], &op[1]); + } inst = emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_NZ)); *predicate = BRW_PREDICATE_ALIGN16_ANY4H; break; case ir_unop_any: + if (brw->gen <= 5) { + resolve_bool_comparison(expr->operands[0], &op[0]); + } inst = emit(CMP(dst_null_d(), op[0], src_reg(0), BRW_CONDITIONAL_NZ)); *predicate = BRW_PREDICATE_ALIGN16_ANY4H; break; @@ -872,6 +901,10 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, case ir_binop_lequal: case ir_binop_equal: case ir_binop_nequal: + if (brw->gen <= 5) { + resolve_bool_comparison(expr->operands[0], &op[0]); + resolve_bool_comparison(expr->operands[1], &op[1]); + } emit(CMP(dst_null_d(), op[0], op[1], brw_conditional_for_comparison(expr->operation))); break; @@ -902,14 +935,8 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, resolve_ud_negate(&this->result); - if (brw->gen >= 6) { - vec4_instruction *inst = emit(AND(dst_null_d(), - this->result, src_reg(1))); - inst->conditional_mod = BRW_CONDITIONAL_NZ; - } else { - vec4_instruction *inst = emit(MOV(dst_null_d(), this->result)); - inst->conditional_mod = BRW_CONDITIONAL_NZ; - } + vec4_instruction *inst = emit(AND(dst_null_d(), this->result, src_reg(1))); + inst->conditional_mod = BRW_CONDITIONAL_NZ; } /** @@ -1322,11 +1349,7 @@ vec4_visitor::visit(ir_expression *ir) switch (ir->operation) { case ir_unop_logic_not: - if (ctx->Const.UniformBooleanTrue != 1) { - emit(NOT(result_dst, op[0])); - } else { - emit(XOR(result_dst, op[0], src_reg(1))); - } + emit(NOT(result_dst, op[0])); break; case ir_unop_neg: op[0].negate = !op[0].negate; @@ -1512,11 +1535,12 @@ vec4_visitor::visit(ir_expression *ir) case ir_binop_gequal: case ir_binop_equal: case ir_binop_nequal: { + if (brw->gen <= 5) { + resolve_bool_comparison(ir->operands[0], &op[0]); + resolve_bool_comparison(ir->operands[1], &op[1]); + } emit(CMP(result_dst, op[0], op[1], brw_conditional_for_comparison(ir->operation))); - if (ctx->Const.UniformBooleanTrue == 1) { - emit(AND(result_dst, result_src, src_reg(1))); - } break; } @@ -1530,9 +1554,6 @@ vec4_visitor::visit(ir_expression *ir) inst->predicate = BRW_PREDICATE_ALIGN16_ALL4H; } else { emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_Z)); - if (ctx->Const.UniformBooleanTrue == 1) { - emit(AND(result_dst, result_src, src_reg(1))); - } } break; case ir_binop_any_nequal: @@ -1546,9 +1567,6 @@ vec4_visitor::visit(ir_expression *ir) inst->predicate = BRW_PREDICATE_ALIGN16_ANY4H; } else { emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_NZ)); - if (ctx->Const.UniformBooleanTrue == 1) { - emit(AND(result_dst, result_src, src_reg(1))); - } } break; @@ -1610,28 +1628,22 @@ vec4_visitor::visit(ir_expression *ir) emit(MOV(result_dst, op[0])); break; case ir_unop_b2i: - if (ctx->Const.UniformBooleanTrue != 1) { - emit(AND(result_dst, op[0], src_reg(1))); - } else { - emit(MOV(result_dst, op[0])); - } + emit(AND(result_dst, op[0], src_reg(1))); break; case ir_unop_b2f: - if (ctx->Const.UniformBooleanTrue != 1) { - op[0].type = BRW_REGISTER_TYPE_D; - result_dst.type = BRW_REGISTER_TYPE_D; - emit(AND(result_dst, op[0], src_reg(0x3f800000u))); - result_dst.type = BRW_REGISTER_TYPE_F; - } else { - emit(MOV(result_dst, op[0])); + if (brw->gen <= 5) { + resolve_bool_comparison(ir->operands[0], &op[0]); } + op[0].type = BRW_REGISTER_TYPE_D; + result_dst.type = BRW_REGISTER_TYPE_D; + emit(AND(result_dst, op[0], src_reg(0x3f800000u))); + result_dst.type = BRW_REGISTER_TYPE_F; break; case ir_unop_f2b: - case ir_unop_i2b: emit(CMP(result_dst, op[0], src_reg(0.0f), BRW_CONDITIONAL_NZ)); - if (ctx->Const.UniformBooleanTrue == 1) { - emit(AND(result_dst, result_src, src_reg(1))); - } + break; + case ir_unop_i2b: + emit(AND(result_dst, op[0], src_reg(1))); break; case ir_unop_trunc: @@ -1777,9 +1789,6 @@ vec4_visitor::visit(ir_expression *ir) if (ir->type->base_type == GLSL_TYPE_BOOL) { emit(CMP(result_dst, packed_consts, src_reg(0u), BRW_CONDITIONAL_NZ)); - if (ctx->Const.UniformBooleanTrue == 1) { - emit(AND(result_dst, result, src_reg(1))); - } } else { emit(MOV(result_dst, packed_consts)); } @@ -3535,6 +3544,27 @@ vec4_visitor::resolve_ud_negate(src_reg *reg) *reg = temp; } +/** + * Resolve the result of a Gen4-5 CMP instruction to a proper boolean. + * + * CMP on Gen4-5 only sets the LSB of the result; the rest are undefined. + * If we need a proper boolean value, we have to fix it up to be 0 or ~0. + */ +void +vec4_visitor::resolve_bool_comparison(ir_rvalue *rvalue, src_reg *reg) +{ + assert(brw->gen <= 5); + + if (!rvalue->type->is_boolean()) + return; + + src_reg and_result = src_reg(this, rvalue->type); + src_reg neg_result = src_reg(this, rvalue->type); + emit(AND(dst_reg(and_result), *reg, src_reg(1))); + emit(MOV(dst_reg(neg_result), negate(and_result))); + *reg = neg_result; +} + vec4_visitor::vec4_visitor(struct brw_context *brw, struct brw_vec4_compile *c, struct gl_program *prog, |