i965/vec4: add VEC4_OPCODE_PICK_{LOW,HIGH}_32BIT opcodes
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 31 May 2016 08:17:37 +0000 (10:17 +0200)
committerSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Tue, 3 Jan 2017 10:26:50 +0000 (11:26 +0100)
These opcodes will pick the low/high 32-bit in each 64-bit data element
using Align1 mode. We will use this, for example, to do things like
unpackDouble2x32.

We use Align1 mode because in order to implement this in Align16 mode
we would need to use 32-bit logical swizzles (XZ for low, YW for high),
but the IR works in terms of 64-bit logical swizzles for DF operands
all the way up to codegen.

v2:
 - use suboffset() instead of get_element_ud()
 - no need to set the width on the dst

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/drivers/dri/i965/brw_vec4.cpp
src/mesa/drivers/dri/i965/brw_vec4_generator.cpp

index 91d9d5225b9d4ea38da977bb8564d89106050843..6c981cc5518c2cdc0b1178ce3959d403fa9f1c1a 100644 (file)
@@ -1100,6 +1100,8 @@ enum opcode {
    VEC4_OPCODE_UNPACK_UNIFORM,
    VEC4_OPCODE_DOUBLE_TO_FLOAT,
    VEC4_OPCODE_FLOAT_TO_DOUBLE,
+   VEC4_OPCODE_PICK_LOW_32BIT,
+   VEC4_OPCODE_PICK_HIGH_32BIT,
 
    FS_OPCODE_DDX_COARSE,
    FS_OPCODE_DDX_FINE,
index ec321ae1910f1f9f4a7e1e87130cc8043c6c8648..bea65050211495c76011bfba6d8d8aefc9263e03 100644 (file)
@@ -326,6 +326,10 @@ brw_instruction_name(const struct gen_device_info *devinfo, enum opcode op)
       return "double_to_float";
    case VEC4_OPCODE_FLOAT_TO_DOUBLE:
       return "float_to_double";
+   case VEC4_OPCODE_PICK_LOW_32BIT:
+      return "pick_low_32bit";
+   case VEC4_OPCODE_PICK_HIGH_32BIT:
+      return "pick_high_32bit";
 
    case FS_OPCODE_DDX_COARSE:
       return "ddx_coarse";
index 4286a6c78aae5ee41ebf60e97c9a5bac14909400..d70b8db244ec6ff3409dfabee5ab2adc03881f96 100644 (file)
@@ -255,6 +255,8 @@ vec4_instruction::can_do_writemask(const struct gen_device_info *devinfo)
    case SHADER_OPCODE_GEN4_SCRATCH_READ:
    case VEC4_OPCODE_DOUBLE_TO_FLOAT:
    case VEC4_OPCODE_FLOAT_TO_DOUBLE:
+   case VEC4_OPCODE_PICK_LOW_32BIT:
+   case VEC4_OPCODE_PICK_HIGH_32BIT:
    case VS_OPCODE_PULL_CONSTANT_LOAD:
    case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7:
    case VS_OPCODE_SET_SIMD4X2_HEADER_GEN9:
@@ -510,6 +512,8 @@ vec4_visitor::opt_reduce_swizzle()
 
       case VEC4_OPCODE_FLOAT_TO_DOUBLE:
       case VEC4_OPCODE_DOUBLE_TO_FLOAT:
+      case VEC4_OPCODE_PICK_LOW_32BIT:
+      case VEC4_OPCODE_PICK_HIGH_32BIT:
          swizzle = brw_swizzle_for_size(4);
          break;
 
index 7864be1f733708b7403e274cc1b28f15629b4e32..0a962e05d1e2b41bc6a1cdc814ca382a43357c2d 100644 (file)
@@ -1953,6 +1953,31 @@ generate_code(struct brw_codegen *p,
          break;
       }
 
+      case VEC4_OPCODE_PICK_LOW_32BIT:
+      case VEC4_OPCODE_PICK_HIGH_32BIT: {
+         /* Stores the low/high 32-bit of each 64-bit element in src[0] into
+          * dst using ALIGN1 mode and a <8,4,2>:UD region on the source.
+          */
+         assert(type_sz(src[0].type) == 8);
+         assert(type_sz(dst.type) == 4);
+
+         brw_set_default_access_mode(p, BRW_ALIGN_1);
+
+         dst = retype(dst, BRW_REGISTER_TYPE_UD);
+         dst.hstride = BRW_HORIZONTAL_STRIDE_1;
+
+         src[0] = retype(src[0], BRW_REGISTER_TYPE_UD);
+         if (inst->opcode == VEC4_OPCODE_PICK_HIGH_32BIT)
+            src[0] = suboffset(src[0], 1);
+         src[0].vstride = BRW_VERTICAL_STRIDE_8;
+         src[0].width = BRW_WIDTH_4;
+         src[0].hstride = BRW_HORIZONTAL_STRIDE_2;
+         brw_MOV(p, dst, src[0]);
+
+         brw_set_default_access_mode(p, BRW_ALIGN_16);
+         break;
+      }
+
       case VEC4_OPCODE_PACK_BYTES: {
          /* Is effectively:
           *