diff options
| author | Eric Anholt <eric@anholt.net> | 2010-10-19 12:32:55 -0700 | 
|---|---|---|
| committer | Eric Anholt <eric@anholt.net> | 2010-10-19 21:17:55 -0700 | 
| commit | ae5698e60467db2a7e3f730788cdcdd3711da101 (patch) | |
| tree | f4d9b858f6e1cfdb144bc640a1d22faad141183a /src | |
| parent | 6ea108e7db79cb7135a8a1ef216e25381f72c225 (diff) | |
i965: Use the new style of IF statement with embedded comparison on gen6.
"Everyone else" does it this way, so follow suit.  It's fewer
instructions, anyway.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 116 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.h | 1 | 
2 files changed, 113 insertions, 4 deletions
| diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index df34089e85..1a5808f44e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -1447,6 +1447,104 @@ fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)     }  } +/** + * Emit a gen6 IF statement with the comparison folded into the IF + * instruction. + */ +void +fs_visitor::emit_if_gen6(ir_if *ir) +{ +   ir_expression *expr = ir->condition->as_expression(); + +   if (expr) { +      fs_reg op[2]; +      fs_inst *inst; +      fs_reg temp; + +      for (unsigned int i = 0; i < expr->get_num_operands(); i++) { +	 assert(expr->operands[i]->type->is_scalar()); + +	 expr->operands[i]->accept(this); +	 op[i] = this->result; +      } + +      switch (expr->operation) { +      case ir_unop_logic_not: +	 inst = emit(fs_inst(BRW_OPCODE_IF, temp, op[0], fs_reg(1))); +	 inst->conditional_mod = BRW_CONDITIONAL_Z; +	 return; + +      case ir_binop_logic_xor: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 return; + +      case ir_binop_logic_or: +	 temp = fs_reg(this, glsl_type::bool_type); +	 emit(fs_inst(BRW_OPCODE_OR, temp, op[0], op[1])); +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, temp, fs_reg(0))); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 return; + +      case ir_binop_logic_and: +	 temp = fs_reg(this, glsl_type::bool_type); +	 emit(fs_inst(BRW_OPCODE_AND, temp, op[0], op[1])); +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, temp, fs_reg(0))); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 return; + +      case ir_unop_f2b: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_f, op[0], fs_reg(0))); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 return; + +      case ir_unop_i2b: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], fs_reg(0))); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 return; + +      case ir_binop_greater: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_G; +	 return; +      case ir_binop_gequal: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_GE; +	 return; +      case ir_binop_less: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_L; +	 return; +      case ir_binop_lequal: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_LE; +	 return; +      case ir_binop_equal: +      case ir_binop_all_equal: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_Z; +	 return; +      case ir_binop_nequal: +      case ir_binop_any_nequal: +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], op[1])); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 return; +      default: +	 assert(!"not reached"); +	 inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, op[0], fs_reg(0))); +	 inst->conditional_mod = BRW_CONDITIONAL_NZ; +	 this->fail = true; +	 return; +      } +      return; +   } + +   ir->condition->accept(this); + +   fs_inst *inst = emit(fs_inst(BRW_OPCODE_IF, reg_null_d, this->result, fs_reg(0))); +   inst->conditional_mod = BRW_CONDITIONAL_NZ; +} +  void  fs_visitor::visit(ir_if *ir)  { @@ -1457,10 +1555,14 @@ fs_visitor::visit(ir_if *ir)      */     this->base_ir = ir->condition; -   emit_bool_to_cond_code(ir->condition); +   if (intel->gen >= 6) { +      emit_if_gen6(ir); +   } else { +      emit_bool_to_cond_code(ir->condition); -   inst = emit(fs_inst(BRW_OPCODE_IF)); -   inst->predicated = true; +      inst = emit(fs_inst(BRW_OPCODE_IF)); +      inst->predicated = true; +   }     foreach_iter(exec_list_iterator, iter, ir->then_instructions) {        ir_instruction *ir = (ir_instruction *)iter.get(); @@ -3066,10 +3168,16 @@ fs_visitor::generate_code()        case BRW_OPCODE_IF:  	 assert(if_stack_depth < 16); -	 if_stack[if_stack_depth] = brw_IF(p, BRW_EXECUTE_8); +	 if (inst->src[0].file != BAD_FILE) { +	    assert(intel->gen >= 6); +	    if_stack[if_stack_depth] = brw_IF_gen6(p, inst->conditional_mod, src[0], src[1]); +	 } else { +	    if_stack[if_stack_depth] = brw_IF(p, BRW_EXECUTE_8); +	 }  	 if_depth_in_loop[loop_stack_depth]++;  	 if_stack_depth++;  	 break; +        case BRW_OPCODE_ELSE:  	 if_stack[if_stack_depth - 1] =  	    brw_ELSE(p, if_stack[if_stack_depth - 1]); diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index b7f4e15c76..b8126083f9 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -390,6 +390,7 @@ public:     fs_inst *emit_math(fs_opcodes op, fs_reg dst, fs_reg src0);     fs_inst *emit_math(fs_opcodes op, fs_reg dst, fs_reg src0, fs_reg src1);     void emit_bool_to_cond_code(ir_rvalue *condition); +   void emit_if_gen6(ir_if *ir);     void emit_fb_writes();     void emit_assignment_writes(fs_reg &l, fs_reg &r, | 
