i965: Fix the new implementation of ir_unop_sign to match brw_wm_emit.c
authorEric Anholt <eric@anholt.net>
Sun, 29 Aug 2010 05:42:01 +0000 (22:42 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 30 Aug 2010 17:26:05 +0000 (10:26 -0700)
Like the comparison operations, this suffered from CMP only setting
the low bit.  Doing the AND instructions would be the same instruction
count as the more obvious conditional moves, so do cond moves.

Fixes glsl-fs-sign and 6 other cases, like trig functions that use
sign() internally.

src/mesa/drivers/dri/i965/brw_fs.cpp

index 233fee47dc5d1d0679414c8e4db113fd5d4f9314..0d29c86ce2a51a55d73a457e2ba4b856a1dc6cf1 100644 (file)
@@ -655,14 +655,17 @@ fs_visitor::visit(ir_expression *ir)
    case ir_unop_sign:
       temp = fs_reg(this, ir->type);
 
-      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], fs_reg(0.0f)));
+      emit(fs_inst(BRW_OPCODE_MOV, this->result, fs_reg(0.0f)));
+
+      inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], fs_reg(0.0f)));
       inst->conditional_mod = BRW_CONDITIONAL_G;
+      inst = emit(fs_inst(BRW_OPCODE_MOV, this->result, fs_reg(1.0f)));
+      inst->predicated = true;
 
-      inst = emit(fs_inst(BRW_OPCODE_CMP, temp, op[0], fs_reg(0.0f)));
+      inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], fs_reg(0.0f)));
       inst->conditional_mod = BRW_CONDITIONAL_L;
-
-      temp.negate = true;
-      emit(fs_inst(BRW_OPCODE_ADD, this->result, this->result, temp));
+      inst = emit(fs_inst(BRW_OPCODE_MOV, this->result, fs_reg(-1.0f)));
+      inst->predicated = true;
 
       break;
    case ir_unop_rcp: