i965: Handle negated unsigned immediate values in constant propagation.
authorFrancisco Jerez <currojerez@riseup.net>
Fri, 6 Feb 2015 12:38:20 +0000 (14:38 +0200)
committerFrancisco Jerez <currojerez@riseup.net>
Tue, 10 Feb 2015 17:09:25 +0000 (19:09 +0200)
Negation of UD/UW sources behaves the same as for D/W sources, taking
the two's complement of the source, except for bitwise logical
operations on Gen8 and up which take the one's complement.  Fixes
crash in a GLSL shader with subtraction of two unsigned values.

Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp

index 60a1b8cf4635c18f3f254dbb79dcae4b722dae93..3bc4435ac92938ecf9dfa9156640edcb37f203d8 100644 (file)
@@ -453,13 +453,15 @@ fs_visitor::try_constant_propagate(fs_inst *inst, acp_entry *entry)
       val.type = inst->src[i].type;
 
       if (inst->src[i].abs) {
-         if (!brw_abs_immediate(val.type, &val.fixed_hw_reg)) {
+         if ((brw->gen >= 8 && is_logic_op(inst->opcode)) ||
+             !brw_abs_immediate(val.type, &val.fixed_hw_reg)) {
             continue;
          }
       }
 
       if (inst->src[i].negate) {
-         if (!brw_negate_immediate(val.type, &val.fixed_hw_reg)) {
+         if ((brw->gen >= 8 && is_logic_op(inst->opcode)) ||
+             !brw_negate_immediate(val.type, &val.fixed_hw_reg)) {
             continue;
          }
       }
index 807b81ddd1d739614c8dab64559e0698e671c304..d6daac0c383c9b0ea4a29596ddcd5af82b63d22a 100644 (file)
@@ -625,9 +625,11 @@ brw_negate_immediate(enum brw_reg_type type, struct brw_reg *reg)
 {
    switch (type) {
    case BRW_REGISTER_TYPE_D:
+   case BRW_REGISTER_TYPE_UD:
       reg->dw1.d = -reg->dw1.d;
       return true;
    case BRW_REGISTER_TYPE_W:
+   case BRW_REGISTER_TYPE_UW:
       reg->dw1.d = -(int16_t)reg->dw1.ud;
       return true;
    case BRW_REGISTER_TYPE_F:
@@ -639,12 +641,6 @@ brw_negate_immediate(enum brw_reg_type type, struct brw_reg *reg)
    case BRW_REGISTER_TYPE_UB:
    case BRW_REGISTER_TYPE_B:
       unreachable("no UB/B immediates");
-   case BRW_REGISTER_TYPE_UD:
-   case BRW_REGISTER_TYPE_UW:
-      /* Presumably the negate modifier on an unsigned source is the same as
-       * on a signed source but it would be nice to confirm.
-       */
-      assert(!"unimplemented: negate UD/UW immediate");
    case BRW_REGISTER_TYPE_UV:
    case BRW_REGISTER_TYPE_V:
       assert(!"unimplemented: negate UV/V immediate");
index 81567d2b295724c7d53e1842d174d9d8fa415956..4614e07c4ec366c1d3450cad705d56b0570349db 100644 (file)
@@ -95,6 +95,15 @@ swizzle_vf_imm(unsigned vf4, unsigned swizzle)
    return ret.vf4;
 }
 
+static bool
+is_logic_op(enum opcode opcode)
+{
+   return (opcode == BRW_OPCODE_AND ||
+           opcode == BRW_OPCODE_OR  ||
+           opcode == BRW_OPCODE_XOR ||
+           opcode == BRW_OPCODE_NOT);
+}
+
 static bool
 try_constant_propagate(struct brw_context *brw, vec4_instruction *inst,
                        int arg, struct copy_entry *entry)
@@ -114,13 +123,15 @@ try_constant_propagate(struct brw_context *brw, vec4_instruction *inst,
       return false;
 
    if (inst->src[arg].abs) {
-      if (!brw_abs_immediate(value.type, &value.fixed_hw_reg)) {
+      if ((brw->gen >= 8 && is_logic_op(inst->opcode)) ||
+          !brw_abs_immediate(value.type, &value.fixed_hw_reg)) {
          return false;
       }
    }
 
    if (inst->src[arg].negate) {
-      if (!brw_negate_immediate(value.type, &value.fixed_hw_reg)) {
+      if ((brw->gen >= 8 && is_logic_op(inst->opcode)) ||
+          !brw_negate_immediate(value.type, &value.fixed_hw_reg)) {
          return false;
       }
    }
@@ -225,15 +236,6 @@ try_constant_propagate(struct brw_context *brw, vec4_instruction *inst,
    return false;
 }
 
-static bool
-is_logic_op(enum opcode opcode)
-{
-   return (opcode == BRW_OPCODE_AND ||
-           opcode == BRW_OPCODE_OR  ||
-           opcode == BRW_OPCODE_XOR ||
-           opcode == BRW_OPCODE_NOT);
-}
-
 static bool
 try_copy_propagate(struct brw_context *brw, vec4_instruction *inst,
                    int arg, struct copy_entry *entry, int reg)