intel/vec4: Fix lowering of multiplication by 16-bit constant
authorCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Mon, 16 Dec 2019 22:43:53 +0000 (14:43 -0800)
committerCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Tue, 17 Dec 2019 18:45:22 +0000 (10:45 -0800)
Existing code was ignoring whether the type of the immediate source
was signed or not.  If the source was signed, it would ignore small
negative values but it also would wrongly accept values between
INT16_MAX and UINT16_MAX, causing the atual value to later be
reinterpreted as a negative number (under 16-bits).

Fixes tests/shaders/glsl-mul-const.shader_test in Piglit for older
platforms that don't support MUL with 32x32 types and use vec4.

Cc: <mesa-stable@lists.freedesktop.org>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/intel/compiler/brw_vec4_nir.cpp

index 3036abcb814be32affffee2b0d1266afd1bc4567..416b6514ad10969da353bef0f2e59951ef88ae86 100644 (file)
@@ -1109,6 +1109,18 @@ vec4_visitor::fix_float_operands(src_reg op[3], nir_alu_instr *instr)
    }
 }
 
+static bool
+const_src_fits_in_16_bits(const nir_src &src, brw_reg_type type)
+{
+   assert(nir_src_is_const(src));
+   if (type_is_unsigned_int(type)) {
+      return nir_src_comp_as_uint(src, 0) <= UINT16_MAX;
+   } else {
+      const int64_t c = nir_src_comp_as_int(src, 0);
+      return c <= INT16_MAX && c >= INT16_MIN;
+   }
+}
+
 void
 vec4_visitor::nir_emit_alu(nir_alu_instr *instr)
 {
@@ -1217,14 +1229,14 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr)
           */
          if (nir_src_is_const(instr->src[0].src) &&
              nir_alu_instr_src_read_mask(instr, 0) == 1 &&
-             nir_src_comp_as_uint(instr->src[0].src, 0) < (1 << 16)) {
+             const_src_fits_in_16_bits(instr->src[0].src, op[0].type)) {
             if (devinfo->gen < 7)
                emit(MUL(dst, op[0], op[1]));
             else
                emit(MUL(dst, op[1], op[0]));
          } else if (nir_src_is_const(instr->src[1].src) &&
                     nir_alu_instr_src_read_mask(instr, 1) == 1 &&
-                    nir_src_comp_as_uint(instr->src[1].src, 0) < (1 << 16)) {
+                    const_src_fits_in_16_bits(instr->src[1].src, op[1].type)) {
             if (devinfo->gen < 7)
                emit(MUL(dst, op[1], op[0]));
             else