summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp9
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp22
3 files changed, 32 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 848e298e80e..a83a6b24dbc 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp
index a5f6f93879a..c3a9deee76b 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 0ea6d317e09..02ecdaf3c91 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -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)