diff options
author | Eric Anholt <[email protected]> | 2012-09-22 17:25:20 +0200 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2012-10-08 08:38:49 -0700 |
commit | d81d7a4b65565a873338f54b0a17795d91ccc625 (patch) | |
tree | c7dfb3fd667ee8a9acc171f90659ea05fe0b94a8 | |
parent | 5c268745465640b4b8504d1e7f79efb25b67cd7a (diff) |
i965/fs: Pull ir_binop_min/ir_binop_max handling to a separate function.
This will be reused from the ARB_fp compiler. I touched up the pre-gen6 path
to not overwrite dst in the first instruction, which prevents the need for
aliasing checks (we'll need that in the ARB_fp compiler, but it actually
hasn't been needed in this codebase since the revert of the nasty old
MOV-avoidance code). I also made the conditional_mod between gen6 and
pre-gen6 consistent, which shouldn't matter except for denorm/(+/-)0
comparisons where the choice between left and right hand side of the
comparison changes.
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.h | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 52 |
2 files changed, 23 insertions, 31 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 72b51b719bd..2209e416b6d 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -316,6 +316,8 @@ public: fs_reg shadow_comp, fs_reg lod, fs_reg lod2); fs_inst *emit_math(enum opcode op, fs_reg dst, fs_reg src0); fs_inst *emit_math(enum opcode op, fs_reg dst, fs_reg src0, fs_reg src1); + void emit_minmax(uint32_t conditionalmod, fs_reg dst, + fs_reg src0, fs_reg src1); bool try_emit_saturate(ir_expression *ir); bool try_emit_mad(ir_expression *ir, int mul_arg); void emit_bool_to_cond_code(ir_rvalue *condition); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index f60b622b67b..134238d42a6 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -178,6 +178,24 @@ fs_visitor::visit(ir_dereference_array *ir) } } +void +fs_visitor::emit_minmax(uint32_t conditionalmod, fs_reg dst, + fs_reg src0, fs_reg src1) +{ + fs_inst *inst; + + if (intel->gen >= 6) { + inst = emit(BRW_OPCODE_SEL, dst, src0, src1); + inst->conditional_mod = conditionalmod; + } else { + inst = emit(BRW_OPCODE_CMP, reg_null_cmp, src0, src1); + inst->conditional_mod = conditionalmod; + + inst = emit(BRW_OPCODE_SEL, dst, src0, src1); + inst->predicated = true; + } +} + /* Instruction selection: Produce a MOV.sat instead of * MIN(MAX(val, 0), 1) when possible. */ @@ -515,40 +533,12 @@ fs_visitor::visit(ir_expression *ir) break; case ir_binop_min: - resolve_ud_negate(&op[0]); - resolve_ud_negate(&op[1]); - - if (intel->gen >= 6) { - inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]); - inst->conditional_mod = BRW_CONDITIONAL_L; - } else { - /* Unalias the destination */ - this->result = fs_reg(this, ir->type); - - inst = emit(BRW_OPCODE_CMP, this->result, op[0], op[1]); - inst->conditional_mod = BRW_CONDITIONAL_L; - - inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]); - inst->predicated = true; - } - break; case ir_binop_max: resolve_ud_negate(&op[0]); resolve_ud_negate(&op[1]); - - if (intel->gen >= 6) { - inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]); - inst->conditional_mod = BRW_CONDITIONAL_GE; - } else { - /* Unalias the destination */ - this->result = fs_reg(this, ir->type); - - inst = emit(BRW_OPCODE_CMP, this->result, op[0], op[1]); - inst->conditional_mod = BRW_CONDITIONAL_G; - - inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]); - inst->predicated = true; - } + emit_minmax(ir->operation == ir_binop_min ? + BRW_CONDITIONAL_L : BRW_CONDITIONAL_GE, + this->result, op[0], op[1]); break; case ir_binop_pow: |