i965: Handle negated unsigned immediate values in constant propagation.

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>
This commit is contained in:
Francisco Jerez 2015-02-06 14:38:20 +02:00
parent 64fde7b31c
commit aef83957e1
3 changed files with 19 additions and 19 deletions

View 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;
}
}

View 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");

View 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)