i965/vs: Fix comparisons with uint negation.
authorEric Anholt <eric@anholt.net>
Mon, 3 Oct 2011 22:31:52 +0000 (15:31 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 20 Oct 2011 16:51:58 +0000 (09:51 -0700)
The condmod instruction ends up generating garbage condition codes,
because apparently the comparison happens on the accumulator value (33
bits for UD), not the truncated value that would be written.

Fixes vs-op-neg-*

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/dri/i965/brw_vec4.h
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp

index 848e298e80e8a90bcc30c6aab6c535bb3a675cfe..a83a6b24dbc578b659d8e733afafb1cede093e2b 100644 (file)
@@ -510,6 +510,7 @@ public:
                                int base_offset);
 
    bool try_emit_sat(ir_expression *ir);
+   void resolve_ud_negate(src_reg *reg);
 
    bool process_move_condition(ir_rvalue *ir);
 
index a5f6f93879a810cc64174183a4b61f27a2c00f3b..c3a9deee76b8b3f5923c6dac1c60ebe07b9914d1 100644 (file)
@@ -205,6 +205,15 @@ try_copy_propagation(struct intel_context *intel,
    if (intel->gen >= 6 && inst->is_math())
       return false;
 
+   /* We can't copy-propagate a UD negation into a condmod
+    * instruction, because the condmod ends up looking at the 33-bit
+    * signed accumulator value instead of the 32-bit value we wanted
+    */
+   if (inst->conditional_mod &&
+       value.negate &&
+       value.type == BRW_REGISTER_TYPE_UD)
+      return false;
+
    /* Don't report progress if this is a noop. */
    if (value.equals(&inst->src[arg]))
       return false;
index 0ea6d317e097a169397dcf1b993f2f079da6d120..02ecdaf3c910f79bd3c9106174f8812f7f690fcb 100644 (file)
@@ -182,6 +182,9 @@ vec4_visitor::IF(src_reg src0, src_reg src1, uint32_t condition)
 
    vec4_instruction *inst;
 
+   resolve_ud_negate(&src0);
+   resolve_ud_negate(&src1);
+
    inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_IF, dst_null_d(),
                                        src0, src1);
    inst->conditional_mod = condition;
@@ -209,6 +212,9 @@ vec4_visitor::CMP(dst_reg dst, src_reg src0, src_reg src1, uint32_t condition)
         dst.fixed_hw_reg.type = dst.type;
    }
 
+   resolve_ud_negate(&src0);
+   resolve_ud_negate(&src1);
+
    inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_CMP, dst, src0, src1);
    inst->conditional_mod = condition;
 
@@ -643,6 +649,8 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, uint32_t *predicate)
       for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
         expr->operands[i]->accept(this);
         op[i] = this->result;
+
+        resolve_ud_negate(&op[i]);
       }
 
       switch (expr->operation) {
@@ -718,6 +726,8 @@ vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, uint32_t *predicate)
 
    ir->accept(this);
 
+   resolve_ud_negate(&this->result);
+
    if (intel->gen >= 6) {
       vec4_instruction *inst = emit(AND(dst_null_d(),
                                        this->result, src_reg(1)));
@@ -2329,6 +2339,18 @@ vec4_visitor::move_uniform_array_access_to_pull_constants()
    split_uniform_registers();
 }
 
+void
+vec4_visitor::resolve_ud_negate(src_reg *reg)
+{
+   if (reg->type != BRW_REGISTER_TYPE_UD ||
+       !reg->negate)
+      return;
+
+   src_reg temp = src_reg(this, glsl_type::uvec4_type);
+   emit(BRW_OPCODE_MOV, dst_reg(temp), *reg);
+   *reg = temp;
+}
+
 vec4_visitor::vec4_visitor(struct brw_vs_compile *c,
                           struct gl_shader_program *prog,
                           struct brw_shader *shader)