/*
 * Copyright © 2015 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "brw_nir.h"
#include "brw_vec4.h"
#include "brw_vec4_builder.h"
#include "brw_vec4_surface_builder.h"
#include "brw_eu.h"

using namespace brw;
using namespace brw::surface_access;

namespace brw {

void
vec4_visitor::emit_nir_code()
{
   if (nir->num_uniforms > 0)
      nir_setup_uniforms();

   nir_emit_impl(nir_shader_get_entrypoint((nir_shader *)nir));
}

void
vec4_visitor::nir_setup_uniforms()
{
   uniforms = nir->num_uniforms / 16;
}

void
vec4_visitor::nir_emit_impl(nir_function_impl *impl)
{
   nir_locals = ralloc_array(mem_ctx, dst_reg, impl->reg_alloc);
   for (unsigned i = 0; i < impl->reg_alloc; i++) {
      nir_locals[i] = dst_reg();
   }

   foreach_list_typed(nir_register, reg, node, &impl->registers) {
      unsigned array_elems =
         reg->num_array_elems == 0 ? 1 : reg->num_array_elems;
      const unsigned num_regs = array_elems * DIV_ROUND_UP(reg->bit_size, 32);
      nir_locals[reg->index] = dst_reg(VGRF, alloc.allocate(num_regs));

      if (reg->bit_size == 64)
         nir_locals[reg->index].type = BRW_REGISTER_TYPE_DF;
   }

   nir_ssa_values = ralloc_array(mem_ctx, dst_reg, impl->ssa_alloc);

   nir_emit_cf_list(&impl->body);
}

void
vec4_visitor::nir_emit_cf_list(exec_list *list)
{
   exec_list_validate(list);
   foreach_list_typed(nir_cf_node, node, node, list) {
      switch (node->type) {
      case nir_cf_node_if:
         nir_emit_if(nir_cf_node_as_if(node));
         break;

      case nir_cf_node_loop:
         nir_emit_loop(nir_cf_node_as_loop(node));
         break;

      case nir_cf_node_block:
         nir_emit_block(nir_cf_node_as_block(node));
         break;

      default:
         unreachable("Invalid CFG node block");
      }
   }
}

void
vec4_visitor::nir_emit_if(nir_if *if_stmt)
{
   /* First, put the condition in f0 */
   src_reg condition = get_nir_src(if_stmt->condition, BRW_REGISTER_TYPE_D, 1);
   vec4_instruction *inst = emit(MOV(dst_null_d(), condition));
   inst->conditional_mod = BRW_CONDITIONAL_NZ;

   /* We can just predicate based on the X channel, as the condition only
    * goes on its own line */
   emit(IF(BRW_PREDICATE_ALIGN16_REPLICATE_X));

   nir_emit_cf_list(&if_stmt->then_list);

   /* note: if the else is empty, dead CF elimination will remove it */
   emit(BRW_OPCODE_ELSE);

   nir_emit_cf_list(&if_stmt->else_list);

   emit(BRW_OPCODE_ENDIF);
}

void
vec4_visitor::nir_emit_loop(nir_loop *loop)
{
   emit(BRW_OPCODE_DO);

   nir_emit_cf_list(&loop->body);

   emit(BRW_OPCODE_WHILE);
}

void
vec4_visitor::nir_emit_block(nir_block *block)
{
   nir_foreach_instr(instr, block) {
      nir_emit_instr(instr);
   }
}

void
vec4_visitor::nir_emit_instr(nir_instr *instr)
{
   base_ir = instr;

   switch (instr->type) {
   case nir_instr_type_load_const:
      nir_emit_load_const(nir_instr_as_load_const(instr));
      break;

   case nir_instr_type_intrinsic:
      nir_emit_intrinsic(nir_instr_as_intrinsic(instr));
      break;

   case nir_instr_type_alu:
      nir_emit_alu(nir_instr_as_alu(instr));
      break;

   case nir_instr_type_jump:
      nir_emit_jump(nir_instr_as_jump(instr));
      break;

   case nir_instr_type_tex:
      nir_emit_texture(nir_instr_as_tex(instr));
      break;

   case nir_instr_type_ssa_undef:
      nir_emit_undef(nir_instr_as_ssa_undef(instr));
      break;

   default:
      unreachable("VS instruction not yet implemented by NIR->vec4");
   }
}

static dst_reg
dst_reg_for_nir_reg(vec4_visitor *v, nir_register *nir_reg,
                    unsigned base_offset, nir_src *indirect)
{
   dst_reg reg;

   reg = v->nir_locals[nir_reg->index];
   if (nir_reg->bit_size == 64)
      reg.type = BRW_REGISTER_TYPE_DF;
   reg = offset(reg, 8, base_offset);
   if (indirect) {
      reg.reladdr =
         new(v->mem_ctx) src_reg(v->get_nir_src(*indirect,
                                                BRW_REGISTER_TYPE_D,
                                                1));
   }
   return reg;
}

dst_reg
vec4_visitor::get_nir_dest(const nir_dest &dest)
{
   if (dest.is_ssa) {
      dst_reg dst =
         dst_reg(VGRF, alloc.allocate(DIV_ROUND_UP(dest.ssa.bit_size, 32)));
      if (dest.ssa.bit_size == 64)
         dst.type = BRW_REGISTER_TYPE_DF;
      nir_ssa_values[dest.ssa.index] = dst;
      return dst;
   } else {
      return dst_reg_for_nir_reg(this, dest.reg.reg, dest.reg.base_offset,
                                 dest.reg.indirect);
   }
}

dst_reg
vec4_visitor::get_nir_dest(const nir_dest &dest, enum brw_reg_type type)
{
   return retype(get_nir_dest(dest), type);
}

dst_reg
vec4_visitor::get_nir_dest(const nir_dest &dest, nir_alu_type type)
{
   return get_nir_dest(dest, brw_type_for_nir_type(devinfo, type));
}

src_reg
vec4_visitor::get_nir_src(const nir_src &src, enum brw_reg_type type,
                          unsigned num_components)
{
   dst_reg reg;

   if (src.is_ssa) {
      assert(src.ssa != NULL);
      reg = nir_ssa_values[src.ssa->index];
   }
   else {
      reg = dst_reg_for_nir_reg(this, src.reg.reg, src.reg.base_offset,
                                src.reg.indirect);
   }

   reg = retype(reg, type);

   src_reg reg_as_src = src_reg(reg);
   reg_as_src.swizzle = brw_swizzle_for_size(num_components);
   return reg_as_src;
}

src_reg
vec4_visitor::get_nir_src(const nir_src &src, nir_alu_type type,
                          unsigned num_components)
{
   return get_nir_src(src, brw_type_for_nir_type(devinfo, type),
                      num_components);
}

src_reg
vec4_visitor::get_nir_src(const nir_src &src, unsigned num_components)
{
   /* if type is not specified, default to signed int */
   return get_nir_src(src, nir_type_int32, num_components);
}

src_reg
vec4_visitor::get_nir_src_imm(const nir_src &src)
{
   assert(nir_src_num_components(src) == 1);
   assert(nir_src_bit_size(src) == 32);
   return nir_src_is_const(src) ? src_reg(brw_imm_d(nir_src_as_int(src))) :
                                  get_nir_src(src, 1);
}

src_reg
vec4_visitor::get_indirect_offset(nir_intrinsic_instr *instr)
{
   nir_src *offset_src = nir_get_io_offset_src(instr);

   if (nir_src_is_const(*offset_src)) {
      /* The only constant offset we should find is 0.  brw_nir.c's
       * add_const_offset_to_base() will fold other constant offsets
       * into instr->const_index[0].
       */
      assert(nir_src_as_uint(*offset_src) == 0);
      return src_reg();
   }

   return get_nir_src(*offset_src, BRW_REGISTER_TYPE_UD, 1);
}

static src_reg
setup_imm_df(const vec4_builder &bld, double v)
{
   const gen_device_info *devinfo = bld.shader->devinfo;
   assert(devinfo->gen >= 7);

   if (devinfo->gen >= 8)
      return brw_imm_df(v);

   /* gen7.5 does not support DF immediates straighforward but the DIM
    * instruction allows to set the 64-bit immediate value.
    */
   if (devinfo->is_haswell) {
      const vec4_builder ubld = bld.exec_all();
      const dst_reg dst = bld.vgrf(BRW_REGISTER_TYPE_DF);
      ubld.DIM(dst, brw_imm_df(v));
      return swizzle(src_reg(dst), BRW_SWIZZLE_XXXX);
   }

   /* gen7 does not support DF immediates */
   union {
      double d;
      struct {
         uint32_t i1;
         uint32_t i2;
      };
   } di;

   di.d = v;

   /* Write the low 32-bit of the constant to the X:UD channel and the
    * high 32-bit to the Y:UD channel to build the constant in a VGRF.
    * We have to do this twice (offset 0 and offset 1), since a DF VGRF takes
    * two SIMD8 registers in SIMD4x2 execution. Finally, return a swizzle
    * XXXX so any access to the VGRF only reads the constant data in these
    * channels.
    */
   const dst_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD, 2);
   for (unsigned n = 0; n < 2; n++) {
      const vec4_builder ubld = bld.exec_all().group(4, n);
      ubld.MOV(writemask(offset(tmp, 8, n), WRITEMASK_X), brw_imm_ud(di.i1));
      ubld.MOV(writemask(offset(tmp, 8, n), WRITEMASK_Y), brw_imm_ud(di.i2));
   }

   return swizzle(src_reg(retype(tmp, BRW_REGISTER_TYPE_DF)), BRW_SWIZZLE_XXXX);
}

void
vec4_visitor::nir_emit_load_const(nir_load_const_instr *instr)
{
   dst_reg reg;

   if (instr->def.bit_size == 64) {
      reg = dst_reg(VGRF, alloc.allocate(2));
      reg.type = BRW_REGISTER_TYPE_DF;
   } else {
      reg = dst_reg(VGRF, alloc.allocate(1));
      reg.type = BRW_REGISTER_TYPE_D;
   }

   const vec4_builder ibld = vec4_builder(this).at_end();
   unsigned remaining = brw_writemask_for_size(instr->def.num_components);

   /* @FIXME: consider emitting vector operations to save some MOVs in
    * cases where the components are representable in 8 bits.
    * For now, we emit a MOV for each distinct value.
    */
   for (unsigned i = 0; i < instr->def.num_components; i++) {
      unsigned writemask = 1 << i;

      if ((remaining & writemask) == 0)
         continue;

      for (unsigned j = i; j < instr->def.num_components; j++) {
         if ((instr->def.bit_size == 32 &&
              instr->value[i].u32 == instr->value[j].u32) ||
             (instr->def.bit_size == 64 &&
              instr->value[i].f64 == instr->value[j].f64)) {
            writemask |= 1 << j;
         }
      }

      reg.writemask = writemask;
      if (instr->def.bit_size == 64) {
         emit(MOV(reg, setup_imm_df(ibld, instr->value[i].f64)));
      } else {
         emit(MOV(reg, brw_imm_d(instr->value[i].i32)));
      }

      remaining &= ~writemask;
   }

   /* Set final writemask */
   reg.writemask = brw_writemask_for_size(instr->def.num_components);

   nir_ssa_values[instr->def.index] = reg;
}

src_reg
vec4_visitor::get_nir_ssbo_intrinsic_index(nir_intrinsic_instr *instr)
{
   /* SSBO stores are weird in that their index is in src[1] */
   const unsigned src = instr->intrinsic == nir_intrinsic_store_ssbo ? 1 : 0;

   src_reg surf_index;
   if (nir_src_is_const(instr->src[src])) {
      unsigned index = prog_data->base.binding_table.ssbo_start +
                       nir_src_as_uint(instr->src[src]);
      surf_index = brw_imm_ud(index);
   } else {
      surf_index = src_reg(this, glsl_type::uint_type);
      emit(ADD(dst_reg(surf_index), get_nir_src(instr->src[src], 1),
               brw_imm_ud(prog_data->base.binding_table.ssbo_start)));
      surf_index = emit_uniformize(surf_index);
   }

   return surf_index;
}

void
vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
{
   dst_reg dest;
   src_reg src;

   switch (instr->intrinsic) {

   case nir_intrinsic_load_input: {
      assert(nir_dest_bit_size(instr->dest) == 32);
      /* We set EmitNoIndirectInput for VS */
      unsigned load_offset = nir_src_as_uint(instr->src[0]);

      dest = get_nir_dest(instr->dest);
      dest.writemask = brw_writemask_for_size(instr->num_components);

      src = src_reg(ATTR, instr->const_index[0] + load_offset,
                    glsl_type::uvec4_type);
      src = retype(src, dest.type);

      /* Swizzle source based on component layout qualifier */
      src.swizzle = BRW_SWZ_COMP_INPUT(nir_intrinsic_component(instr));
      emit(MOV(dest, src));
      break;
   }

   case nir_intrinsic_store_output: {
      assert(nir_src_bit_size(instr->src[0]) == 32);
      unsigned store_offset = nir_src_as_uint(instr->src[1]);
      int varying = instr->const_index[0] + store_offset;
      src = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_F,
                        instr->num_components);

      unsigned c = nir_intrinsic_component(instr);
      output_reg[varying][c] = dst_reg(src);
      output_num_components[varying][c] = instr->num_components;
      break;
   }

   case nir_intrinsic_get_buffer_size: {
      assert(nir_src_num_components(instr->src[0]) == 1);
      unsigned ssbo_index = nir_src_is_const(instr->src[0]) ?
                            nir_src_as_uint(instr->src[0]) : 0;

      const unsigned index =
         prog_data->base.binding_table.ssbo_start + ssbo_index;
      dst_reg result_dst = get_nir_dest(instr->dest);
      vec4_instruction *inst = new(mem_ctx)
         vec4_instruction(SHADER_OPCODE_GET_BUFFER_SIZE, result_dst);

      inst->base_mrf = 2;
      inst->mlen = 1; /* always at least one */
      inst->src[1] = brw_imm_ud(index);

      /* MRF for the first parameter */
      src_reg lod = brw_imm_d(0);
      int param_base = inst->base_mrf;
      int writemask = WRITEMASK_X;
      emit(MOV(dst_reg(MRF, param_base, glsl_type::int_type, writemask), lod));

      emit(inst);
      break;
   }

   case nir_intrinsic_store_ssbo: {
      assert(devinfo->gen >= 7);

      /* brw_nir_lower_mem_access_bit_sizes takes care of this */
      assert(nir_src_bit_size(instr->src[0]) == 32);
      assert(nir_intrinsic_write_mask(instr) ==
             (1u << instr->num_components) - 1);

      src_reg surf_index = get_nir_ssbo_intrinsic_index(instr);
      src_reg offset_reg = retype(get_nir_src_imm(instr->src[2]),
                                  BRW_REGISTER_TYPE_UD);

      /* Value */
      src_reg val_reg = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_F, 4);

      /* IvyBridge does not have a native SIMD4x2 untyped write message so untyped
       * writes will use SIMD8 mode. In order to hide this and keep symmetry across
       * typed and untyped messages and across hardware platforms, the
       * current implementation of the untyped messages will transparently convert
       * the SIMD4x2 payload into an equivalent SIMD8 payload by transposing it
       * and enabling only channel X on the SEND instruction.
       *
       * The above, works well for full vector writes, but not for partial writes
       * where we want to write some channels and not others, like when we have
       * code such as v.xyw = vec3(1,2,4). Because the untyped write messages are
       * quite restrictive with regards to the channel enables we can configure in
       * the message descriptor (not all combinations are allowed) we cannot simply
       * implement these scenarios with a single message while keeping the
       * aforementioned symmetry in the implementation. For now we de decided that
       * it is better to keep the symmetry to reduce complexity, so in situations
       * such as the one described we end up emitting two untyped write messages
       * (one for xy and another for w).
       *
       * The code below packs consecutive channels into a single write message,
       * detects gaps in the vector write and if needed, sends a second message
       * with the remaining channels. If in the future we decide that we want to
       * emit a single message at the expense of losing the symmetry in the
       * implementation we can:
       *
       * 1) For IvyBridge: Only use the red channel of the untyped write SIMD8
       *    message payload. In this mode we can write up to 8 offsets and dwords
       *    to the red channel only (for the two vec4s in the SIMD4x2 execution)
       *    and select which of the 8 channels carry data to write by setting the
       *    appropriate writemask in the dst register of the SEND instruction.
       *    It would require to write a new generator opcode specifically for
       *    IvyBridge since we would need to prepare a SIMD8 payload that could
       *    use any channel, not just X.
       *
       * 2) For Haswell+: Simply send a single write message but set the writemask
       *    on the dst of the SEND instruction to select the channels we want to
       *    write. It would require to modify the current messages to receive
       *    and honor the writemask provided.
       */
      const vec4_builder bld = vec4_builder(this).at_end()
                               .annotate(current_annotation, base_ir);

      emit_untyped_write(bld, surf_index, offset_reg, val_reg,
                         1 /* dims */, instr->num_components /* size */,
                         BRW_PREDICATE_NONE);
      break;
   }

   case nir_intrinsic_load_ssbo: {
      assert(devinfo->gen >= 7);

      /* brw_nir_lower_mem_access_bit_sizes takes care of this */
      assert(nir_dest_bit_size(instr->dest) == 32);

      src_reg surf_index = get_nir_ssbo_intrinsic_index(instr);
      src_reg offset_reg = retype(get_nir_src_imm(instr->src[1]),
                                  BRW_REGISTER_TYPE_UD);

      /* Read the vector */
      const vec4_builder bld = vec4_builder(this).at_end()
         .annotate(current_annotation, base_ir);

      src_reg read_result = emit_untyped_read(bld, surf_index, offset_reg,
                                              1 /* dims */, 4 /* size*/,
                                              BRW_PREDICATE_NONE);
      dst_reg dest = get_nir_dest(instr->dest);
      read_result.type = dest.type;
      read_result.swizzle = brw_swizzle_for_size(instr->num_components);
      emit(MOV(dest, read_result));
      break;
   }

   case nir_intrinsic_ssbo_atomic_add:
   case nir_intrinsic_ssbo_atomic_imin:
   case nir_intrinsic_ssbo_atomic_umin:
   case nir_intrinsic_ssbo_atomic_imax:
   case nir_intrinsic_ssbo_atomic_umax:
   case nir_intrinsic_ssbo_atomic_and:
   case nir_intrinsic_ssbo_atomic_or:
   case nir_intrinsic_ssbo_atomic_xor:
   case nir_intrinsic_ssbo_atomic_exchange:
   case nir_intrinsic_ssbo_atomic_comp_swap:
      nir_emit_ssbo_atomic(brw_aop_for_nir_intrinsic(instr), instr);
      break;

   case nir_intrinsic_load_vertex_id:
      unreachable("should be lowered by lower_vertex_id()");

   case nir_intrinsic_load_vertex_id_zero_base:
   case nir_intrinsic_load_base_vertex:
   case nir_intrinsic_load_instance_id:
   case nir_intrinsic_load_base_instance:
   case nir_intrinsic_load_draw_id:
   case nir_intrinsic_load_invocation_id:
      unreachable("should be lowered by brw_nir_lower_vs_inputs()");

   case nir_intrinsic_load_uniform: {
      /* Offsets are in bytes but they should always be multiples of 4 */
      assert(nir_intrinsic_base(instr) % 4 == 0);

      dest = get_nir_dest(instr->dest);

      src = src_reg(dst_reg(UNIFORM, nir_intrinsic_base(instr) / 16));
      src.type = dest.type;

      /* Uniforms don't actually have to be vec4 aligned.  In the case that
       * it isn't, we have to use a swizzle to shift things around.  They
       * do still have the std140 alignment requirement that vec2's have to
       * be vec2-aligned and vec3's and vec4's have to be vec4-aligned.
       *
       * The swizzle also works in the indirect case as the generator adds
       * the swizzle to the offset for us.
       */
      const int type_size = type_sz(src.type);
      unsigned shift = (nir_intrinsic_base(instr) % 16) / type_size;
      assert(shift + instr->num_components <= 4);

      if (nir_src_is_const(instr->src[0])) {
         const unsigned load_offset = nir_src_as_uint(instr->src[0]);
         /* Offsets are in bytes but they should always be multiples of 4 */
         assert(load_offset % 4 == 0);

         src.swizzle = brw_swizzle_for_size(instr->num_components);
         dest.writemask = brw_writemask_for_size(instr->num_components);
         unsigned offset = load_offset + shift * type_size;
         src.offset = ROUND_DOWN_TO(offset, 16);
         shift = (offset % 16) / type_size;
         assert(shift + instr->num_components <= 4);
         src.swizzle += BRW_SWIZZLE4(shift, shift, shift, shift);

         emit(MOV(dest, src));
      } else {
         /* Uniform arrays are vec4 aligned, because of std140 alignment
          * rules.
          */
         assert(shift == 0);

         src_reg indirect = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_UD, 1);

         /* MOV_INDIRECT is going to stomp the whole thing anyway */
         dest.writemask = WRITEMASK_XYZW;

         emit(SHADER_OPCODE_MOV_INDIRECT, dest, src,
              indirect, brw_imm_ud(instr->const_index[1]));
      }
      break;
   }

   case nir_intrinsic_load_ubo: {
      src_reg surf_index;

      prog_data->base.has_ubo_pull = true;

      dest = get_nir_dest(instr->dest);

      if (nir_src_is_const(instr->src[0])) {
         /* The block index is a constant, so just emit the binding table entry
          * as an immediate.
          */
         const unsigned index = prog_data->base.binding_table.ubo_start +
                                nir_src_as_uint(instr->src[0]);
         surf_index = brw_imm_ud(index);
      } else {
         /* The block index is not a constant. Evaluate the index expression
          * per-channel and add the base UBO index; we have to select a value
          * from any live channel.
          */
         surf_index = src_reg(this, glsl_type::uint_type);
         emit(ADD(dst_reg(surf_index), get_nir_src(instr->src[0], nir_type_int32,
                                                   instr->num_components),
                  brw_imm_ud(prog_data->base.binding_table.ubo_start)));
         surf_index = emit_uniformize(surf_index);
      }

      src_reg offset_reg;
      if (nir_src_is_const(instr->src[1])) {
         unsigned load_offset = nir_src_as_uint(instr->src[1]);
         offset_reg = brw_imm_ud(load_offset & ~15);
      } else {
         offset_reg = src_reg(this, glsl_type::uint_type);
         emit(MOV(dst_reg(offset_reg),
                  get_nir_src(instr->src[1], nir_type_uint32, 1)));
      }

      src_reg packed_consts;
      if (nir_dest_bit_size(instr->dest) == 32) {
         packed_consts = src_reg(this, glsl_type::vec4_type);
         emit_pull_constant_load_reg(dst_reg(packed_consts),
                                     surf_index,
                                     offset_reg,
                                     NULL, NULL /* before_block/inst */);
      } else {
         src_reg temp = src_reg(this, glsl_type::dvec4_type);
         src_reg temp_float = retype(temp, BRW_REGISTER_TYPE_F);

         emit_pull_constant_load_reg(dst_reg(temp_float),
                                     surf_index, offset_reg, NULL, NULL);
         if (offset_reg.file == IMM)
            offset_reg.ud += 16;
         else
            emit(ADD(dst_reg(offset_reg), offset_reg, brw_imm_ud(16u)));
         emit_pull_constant_load_reg(dst_reg(byte_offset(temp_float, REG_SIZE)),
                                     surf_index, offset_reg, NULL, NULL);

         packed_consts = src_reg(this, glsl_type::dvec4_type);
         shuffle_64bit_data(dst_reg(packed_consts), temp, false);
      }

      packed_consts.swizzle = brw_swizzle_for_size(instr->num_components);
      if (nir_src_is_const(instr->src[1])) {
         unsigned load_offset = nir_src_as_uint(instr->src[1]);
         unsigned type_size = type_sz(dest.type);
         packed_consts.swizzle +=
            BRW_SWIZZLE4(load_offset % 16 / type_size,
                         load_offset % 16 / type_size,
                         load_offset % 16 / type_size,
                         load_offset % 16 / type_size);
      }

      emit(MOV(dest, retype(packed_consts, dest.type)));

      break;
   }

   case nir_intrinsic_scoped_barrier:
      assert(nir_intrinsic_execution_scope(instr) == NIR_SCOPE_NONE);
      /* Fall through. */
   case nir_intrinsic_memory_barrier: {
      const vec4_builder bld =
         vec4_builder(this).at_end().annotate(current_annotation, base_ir);
      const dst_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD);
      vec4_instruction *fence =
         bld.emit(SHADER_OPCODE_MEMORY_FENCE, tmp, brw_vec8_grf(0, 0));
      fence->sfid = GEN7_SFID_DATAPORT_DATA_CACHE;
      break;
   }

   case nir_intrinsic_shader_clock: {
      /* We cannot do anything if there is an event, so ignore it for now */
      const src_reg shader_clock = get_timestamp();
      const enum brw_reg_type type = brw_type_for_base_type(glsl_type::uvec2_type);

      dest = get_nir_dest(instr->dest, type);
      emit(MOV(dest, shader_clock));
      break;
   }

   default:
      unreachable("Unknown intrinsic");
   }
}

void
vec4_visitor::nir_emit_ssbo_atomic(int op, nir_intrinsic_instr *instr)
{
   dst_reg dest;
   if (nir_intrinsic_infos[instr->intrinsic].has_dest)
      dest = get_nir_dest(instr->dest);

   src_reg surface = get_nir_ssbo_intrinsic_index(instr);
   src_reg offset = get_nir_src(instr->src[1], 1);
   src_reg data1;
   if (op != BRW_AOP_INC && op != BRW_AOP_DEC && op != BRW_AOP_PREDEC)
      data1 = get_nir_src(instr->src[2], 1);
   src_reg data2;
   if (op == BRW_AOP_CMPWR)
      data2 = get_nir_src(instr->src[3], 1);

   /* Emit the actual atomic operation operation */
   const vec4_builder bld =
      vec4_builder(this).at_end().annotate(current_annotation, base_ir);

   src_reg atomic_result = emit_untyped_atomic(bld, surface, offset,
                                               data1, data2,
                                               1 /* dims */, 1 /* rsize */,
                                               op,
                                               BRW_PREDICATE_NONE);
   dest.type = atomic_result.type;
   bld.MOV(dest, atomic_result);
}

static unsigned
brw_swizzle_for_nir_swizzle(uint8_t swizzle[4])
{
   return BRW_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
}

bool
vec4_visitor::optimize_predicate(nir_alu_instr *instr,
                                 enum brw_predicate *predicate)
{
   if (!instr->src[0].src.is_ssa ||
       instr->src[0].src.ssa->parent_instr->type != nir_instr_type_alu)
      return false;

   nir_alu_instr *cmp_instr =
      nir_instr_as_alu(instr->src[0].src.ssa->parent_instr);

   switch (cmp_instr->op) {
   case nir_op_b32any_fnequal2:
   case nir_op_b32any_inequal2:
   case nir_op_b32any_fnequal3:
   case nir_op_b32any_inequal3:
   case nir_op_b32any_fnequal4:
   case nir_op_b32any_inequal4:
      *predicate = BRW_PREDICATE_ALIGN16_ANY4H;
      break;
   case nir_op_b32all_fequal2:
   case nir_op_b32all_iequal2:
   case nir_op_b32all_fequal3:
   case nir_op_b32all_iequal3:
   case nir_op_b32all_fequal4:
   case nir_op_b32all_iequal4:
      *predicate = BRW_PREDICATE_ALIGN16_ALL4H;
      break;
   default:
      return false;
   }

   unsigned size_swizzle =
      brw_swizzle_for_size(nir_op_infos[cmp_instr->op].input_sizes[0]);

   src_reg op[2];
   assert(nir_op_infos[cmp_instr->op].num_inputs == 2);
   for (unsigned i = 0; i < 2; i++) {
      nir_alu_type type = nir_op_infos[cmp_instr->op].input_types[i];
      unsigned bit_size = nir_src_bit_size(cmp_instr->src[i].src);
      type = (nir_alu_type) (((unsigned) type) | bit_size);
      op[i] = get_nir_src(cmp_instr->src[i].src, type, 4);
      unsigned base_swizzle =
         brw_swizzle_for_nir_swizzle(cmp_instr->src[i].swizzle);
      op[i].swizzle = brw_compose_swizzle(size_swizzle, base_swizzle);
   }

   emit(CMP(dst_null_d(), op[0], op[1],
            brw_cmod_for_nir_comparison(cmp_instr->op)));

   return true;
}

static void
emit_find_msb_using_lzd(const vec4_builder &bld,
                        const dst_reg &dst,
                        const src_reg &src,
                        bool is_signed)
{
   vec4_instruction *inst;
   src_reg temp = src;

   if (is_signed) {
      /* LZD of an absolute value source almost always does the right
       * thing.  There are two problem values:
       *
       * * 0x80000000.  Since abs(0x80000000) == 0x80000000, LZD returns
       *   0.  However, findMSB(int(0x80000000)) == 30.
       *
       * * 0xffffffff.  Since abs(0xffffffff) == 1, LZD returns
       *   31.  Section 8.8 (Integer Functions) of the GLSL 4.50 spec says:
       *
       *    For a value of zero or negative one, -1 will be returned.
       *
       * * Negative powers of two.  LZD(abs(-(1<<x))) returns x, but
       *   findMSB(-(1<<x)) should return x-1.
       *
       * For all negative number cases, including 0x80000000 and
       * 0xffffffff, the correct value is obtained from LZD if instead of
       * negating the (already negative) value the logical-not is used.  A
       * conditonal logical-not can be achieved in two instructions.
       */
      temp = src_reg(bld.vgrf(BRW_REGISTER_TYPE_D));

      bld.ASR(dst_reg(temp), src, brw_imm_d(31));
      bld.XOR(dst_reg(temp), temp, src);
   }

   bld.LZD(retype(dst, BRW_REGISTER_TYPE_UD),
           retype(temp, BRW_REGISTER_TYPE_UD));

   /* LZD counts from the MSB side, while GLSL's findMSB() wants the count
    * from the LSB side. Subtract the result from 31 to convert the MSB count
    * into an LSB count.  If no bits are set, LZD will return 32.  31-32 = -1,
    * which is exactly what findMSB() is supposed to return.
    */
   inst = bld.ADD(dst, retype(src_reg(dst), BRW_REGISTER_TYPE_D),
                  brw_imm_d(31));
   inst->src[0].negate = true;
}

void
vec4_visitor::emit_conversion_from_double(dst_reg dst, src_reg src)
{
   /* BDW PRM vol 15 - workarounds:
    * DF->f format conversion for Align16 has wrong emask calculation when
    * source is immediate.
    */
   if (devinfo->gen == 8 && dst.type == BRW_REGISTER_TYPE_F &&
       src.file == BRW_IMMEDIATE_VALUE) {
      emit(MOV(dst, brw_imm_f(src.df)));
      return;
   }

   enum opcode op;
   switch (dst.type) {
   case BRW_REGISTER_TYPE_D:
      op = VEC4_OPCODE_DOUBLE_TO_D32;
      break;
   case BRW_REGISTER_TYPE_UD:
      op = VEC4_OPCODE_DOUBLE_TO_U32;
      break;
   case BRW_REGISTER_TYPE_F:
      op = VEC4_OPCODE_DOUBLE_TO_F32;
      break;
   default:
      unreachable("Unknown conversion");
   }

   dst_reg temp = dst_reg(this, glsl_type::dvec4_type);
   emit(MOV(temp, src));
   dst_reg temp2 = dst_reg(this, glsl_type::dvec4_type);
   emit(op, temp2, src_reg(temp));

   emit(VEC4_OPCODE_PICK_LOW_32BIT, retype(temp2, dst.type), src_reg(temp2));
   emit(MOV(dst, src_reg(retype(temp2, dst.type))));
}

void
vec4_visitor::emit_conversion_to_double(dst_reg dst, src_reg src)
{
   dst_reg tmp_dst = dst_reg(src_reg(this, glsl_type::dvec4_type));
   src_reg tmp_src = retype(src_reg(this, glsl_type::vec4_type), src.type);
   emit(MOV(dst_reg(tmp_src), src));
   emit(VEC4_OPCODE_TO_DOUBLE, tmp_dst, tmp_src);
   emit(MOV(dst, src_reg(tmp_dst)));
}

/**
 * Try to use an immediate value for a source
 *
 * In cases of flow control, constant propagation is sometimes unable to
 * determine that a register contains a constant value.  To work around this,
 * try to emit a literal as one of the sources.  If \c try_src0_also is set,
 * \c op[0] will also be tried for an immediate value.
 *
 * If \c op[0] is modified, the operands will be exchanged so that \c op[1]
 * will always be the immediate value.
 *
 * \return The index of the source that was modified, 0 or 1, if successful.
 * Otherwise, -1.
 *
 * \param op - Operands to the instruction
 * \param try_src0_also - True if \c op[0] should also be a candidate for
 *                        getting an immediate value.  This should only be set
 *                        for commutative operations.
 */
static int
try_immediate_source(const nir_alu_instr *instr, src_reg *op,
                     bool try_src0_also,
                     ASSERTED const gen_device_info *devinfo)
{
   unsigned idx;

   /* MOV should be the only single-source instruction passed to this
    * function.  Any other unary instruction with a constant source should
    * have been constant-folded away!
    */
   assert(nir_op_infos[instr->op].num_inputs > 1 ||
          instr->op == nir_op_mov);

   if (instr->op != nir_op_mov &&
       nir_src_bit_size(instr->src[1].src) == 32 &&
       nir_src_is_const(instr->src[1].src)) {
      idx = 1;
   } else if (try_src0_also &&
         nir_src_bit_size(instr->src[0].src) == 32 &&
         nir_src_is_const(instr->src[0].src)) {
      idx = 0;
   } else {
      return -1;
   }

   const enum brw_reg_type old_type = op[idx].type;

   switch (old_type) {
   case BRW_REGISTER_TYPE_D:
   case BRW_REGISTER_TYPE_UD: {
      int first_comp = -1;
      int d = 0;

      for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++) {
         if (nir_alu_instr_channel_used(instr, idx, i)) {
            if (first_comp < 0) {
               first_comp = i;
               d = nir_src_comp_as_int(instr->src[idx].src,
                                       instr->src[idx].swizzle[i]);
            } else if (d != nir_src_comp_as_int(instr->src[idx].src,
                                                instr->src[idx].swizzle[i])) {
               return -1;
            }
         }
      }

      assert(first_comp >= 0);

      if (op[idx].abs)
         d = MAX2(-d, d);

      if (op[idx].negate) {
         /* On Gen8+ a negation source modifier on a logical operation means
          * something different.  Nothing should generate this, so assert that
          * it does not occur.
          */
         assert(devinfo->gen < 8 || (instr->op != nir_op_iand &&
                                     instr->op != nir_op_ior &&
                                     instr->op != nir_op_ixor));
         d = -d;
      }

      op[idx] = retype(src_reg(brw_imm_d(d)), old_type);
      break;
   }

   case BRW_REGISTER_TYPE_F: {
      int first_comp = -1;
      float f[NIR_MAX_VEC_COMPONENTS] = { 0.0f };
      bool is_scalar = true;

      for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++) {
         if (nir_alu_instr_channel_used(instr, idx, i)) {
            f[i] = nir_src_comp_as_float(instr->src[idx].src,
                                         instr->src[idx].swizzle[i]);
            if (first_comp < 0) {
               first_comp = i;
            } else if (f[first_comp] != f[i]) {
               is_scalar = false;
            }
         }
      }

      if (is_scalar) {
         if (op[idx].abs)
            f[first_comp] = fabs(f[first_comp]);

         if (op[idx].negate)
            f[first_comp] = -f[first_comp];

         op[idx] = src_reg(brw_imm_f(f[first_comp]));
         assert(op[idx].type == old_type);
      } else {
         uint8_t vf_values[4] = { 0, 0, 0, 0 };

         for (unsigned i = 0; i < ARRAY_SIZE(vf_values); i++) {

            if (op[idx].abs)
               f[i] = fabs(f[i]);

            if (op[idx].negate)
               f[i] = -f[i];

            const int vf = brw_float_to_vf(f[i]);
            if (vf == -1)
               return -1;

            vf_values[i] = vf;
         }

         op[idx] = src_reg(brw_imm_vf4(vf_values[0], vf_values[1],
                                       vf_values[2], vf_values[3]));
      }
      break;
   }

   default:
      unreachable("Non-32bit type.");
   }

   /* If the instruction has more than one source, the instruction format only
    * allows source 1 to be an immediate value.  If the immediate value was
    * source 0, then the sources must be exchanged.
    */
   if (idx == 0 && instr->op != nir_op_mov) {
      src_reg tmp = op[0];
      op[0] = op[1];
      op[1] = tmp;
   }

   return idx;
}

void
vec4_visitor::fix_float_operands(src_reg op[3], nir_alu_instr *instr)
{
   bool fixed[3] = { false, false, false };

   for (unsigned i = 0; i < 2; i++) {
      if (!nir_src_is_const(instr->src[i].src))
         continue;

      for (unsigned j = i + 1; j < 3; j++) {
         if (fixed[j])
            continue;

         if (!nir_src_is_const(instr->src[j].src))
            continue;

         if (nir_alu_srcs_equal(instr, instr, i, j)) {
            if (!fixed[i])
               op[i] = fix_3src_operand(op[i]);

            op[j] = op[i];

            fixed[i] = true;
            fixed[j] = true;
         } else if (nir_alu_srcs_negative_equal(instr, instr, i, j)) {
            if (!fixed[i])
               op[i] = fix_3src_operand(op[i]);

            op[j] = op[i];
            op[j].negate = !op[j].negate;

            fixed[i] = true;
            fixed[j] = true;
         }
      }
   }

   for (unsigned i = 0; i < 3; i++) {
      if (!fixed[i])
         op[i] = fix_3src_operand(op[i]);
   }
}

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)
{
   vec4_instruction *inst;

   nir_alu_type dst_type = (nir_alu_type) (nir_op_infos[instr->op].output_type |
                                           nir_dest_bit_size(instr->dest.dest));
   dst_reg dst = get_nir_dest(instr->dest.dest, dst_type);
   dst.writemask = instr->dest.write_mask;

   assert(!instr->dest.saturate);

   src_reg op[4];
   for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
      /* We don't lower to source modifiers, so they shouldn't exist. */
      assert(!instr->src[i].abs);
      assert(!instr->src[i].negate);

      nir_alu_type src_type = (nir_alu_type)
         (nir_op_infos[instr->op].input_types[i] |
          nir_src_bit_size(instr->src[i].src));
      op[i] = get_nir_src(instr->src[i].src, src_type, 4);
      op[i].swizzle = brw_swizzle_for_nir_swizzle(instr->src[i].swizzle);
   }

   switch (instr->op) {
   case nir_op_mov:
      try_immediate_source(instr, &op[0], true, devinfo);
      inst = emit(MOV(dst, op[0]));
      break;

   case nir_op_vec2:
   case nir_op_vec3:
   case nir_op_vec4:
      unreachable("not reached: should be handled by lower_vec_to_movs()");

   case nir_op_i2f32:
   case nir_op_u2f32:
      inst = emit(MOV(dst, op[0]));
      break;

   case nir_op_f2f32:
   case nir_op_f2i32:
   case nir_op_f2u32:
      if (nir_src_bit_size(instr->src[0].src) == 64)
         emit_conversion_from_double(dst, op[0]);
      else
         inst = emit(MOV(dst, op[0]));
      break;

   case nir_op_f2f64:
   case nir_op_i2f64:
   case nir_op_u2f64:
      emit_conversion_to_double(dst, op[0]);
      break;

   case nir_op_fsat:
      inst = emit(MOV(dst, op[0]));
      inst->saturate = true;
      break;

   case nir_op_fneg:
   case nir_op_ineg:
      op[0].negate = true;
      inst = emit(MOV(dst, op[0]));
      break;

   case nir_op_fabs:
   case nir_op_iabs:
      op[0].negate = false;
      op[0].abs = true;
      inst = emit(MOV(dst, op[0]));
      break;

   case nir_op_iadd:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      /* fall through */
   case nir_op_fadd:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit(ADD(dst, op[0], op[1]));
      break;

   case nir_op_uadd_sat:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      inst = emit(ADD(dst, op[0], op[1]));
      inst->saturate = true;
      break;

   case nir_op_fmul:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit(MUL(dst, op[0], op[1]));
      break;

   case nir_op_imul: {
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      if (devinfo->gen < 8) {
         /* For integer multiplication, the MUL uses the low 16 bits of one of
          * the operands (src0 through SNB, src1 on IVB and later). The MACH
          * accumulates in the contribution of the upper 16 bits of that
          * operand. If we can determine that one of the args is in the low
          * 16 bits, though, we can just emit a single MUL.
          */
         if (nir_src_is_const(instr->src[0].src) &&
             nir_alu_instr_src_read_mask(instr, 0) == 1 &&
             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 &&
                    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
               emit(MUL(dst, op[0], op[1]));
         } else {
            struct brw_reg acc = retype(brw_acc_reg(8), dst.type);

            emit(MUL(acc, op[0], op[1]));
            emit(MACH(dst_null_d(), op[0], op[1]));
            emit(MOV(dst, src_reg(acc)));
         }
      } else {
	 emit(MUL(dst, op[0], op[1]));
      }
      break;
   }

   case nir_op_imul_high:
   case nir_op_umul_high: {
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      struct brw_reg acc = retype(brw_acc_reg(8), dst.type);

      if (devinfo->gen >= 8)
         emit(MUL(acc, op[0], retype(op[1], BRW_REGISTER_TYPE_UW)));
      else
         emit(MUL(acc, op[0], op[1]));

      emit(MACH(dst, op[0], op[1]));
      break;
   }

   case nir_op_frcp:
      inst = emit_math(SHADER_OPCODE_RCP, dst, op[0]);
      break;

   case nir_op_fexp2:
      inst = emit_math(SHADER_OPCODE_EXP2, dst, op[0]);
      break;

   case nir_op_flog2:
      inst = emit_math(SHADER_OPCODE_LOG2, dst, op[0]);
      break;

   case nir_op_fsin:
      inst = emit_math(SHADER_OPCODE_SIN, dst, op[0]);
      break;

   case nir_op_fcos:
      inst = emit_math(SHADER_OPCODE_COS, dst, op[0]);
      break;

   case nir_op_idiv:
   case nir_op_udiv:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_math(SHADER_OPCODE_INT_QUOTIENT, dst, op[0], op[1]);
      break;

   case nir_op_umod:
   case nir_op_irem:
      /* According to the sign table for INT DIV in the Ivy Bridge PRM, it
       * appears that our hardware just does the right thing for signed
       * remainder.
       */
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_math(SHADER_OPCODE_INT_REMAINDER, dst, op[0], op[1]);
      break;

   case nir_op_imod: {
      /* Get a regular C-style remainder.  If a % b == 0, set the predicate. */
      inst = emit_math(SHADER_OPCODE_INT_REMAINDER, dst, op[0], op[1]);

      /* Math instructions don't support conditional mod */
      inst = emit(MOV(dst_null_d(), src_reg(dst)));
      inst->conditional_mod = BRW_CONDITIONAL_NZ;

      /* Now, we need to determine if signs of the sources are different.
       * When we XOR the sources, the top bit is 0 if they are the same and 1
       * if they are different.  We can then use a conditional modifier to
       * turn that into a predicate.  This leads us to an XOR.l instruction.
       *
       * Technically, according to the PRM, you're not allowed to use .l on a
       * XOR instruction.  However, emperical experiments and Curro's reading
       * of the simulator source both indicate that it's safe.
       */
      src_reg tmp = src_reg(this, glsl_type::ivec4_type);
      inst = emit(XOR(dst_reg(tmp), op[0], op[1]));
      inst->predicate = BRW_PREDICATE_NORMAL;
      inst->conditional_mod = BRW_CONDITIONAL_L;

      /* If the result of the initial remainder operation is non-zero and the
       * two sources have different signs, add in a copy of op[1] to get the
       * final integer modulus value.
       */
      inst = emit(ADD(dst, src_reg(dst), op[1]));
      inst->predicate = BRW_PREDICATE_NORMAL;
      break;
   }

   case nir_op_ldexp:
      unreachable("not reached: should be handled by ldexp_to_arith()");

   case nir_op_fsqrt:
      inst = emit_math(SHADER_OPCODE_SQRT, dst, op[0]);
      break;

   case nir_op_frsq:
      inst = emit_math(SHADER_OPCODE_RSQ, dst, op[0]);
      break;

   case nir_op_fpow:
      inst = emit_math(SHADER_OPCODE_POW, dst, op[0], op[1]);
      break;

   case nir_op_uadd_carry: {
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      struct brw_reg acc = retype(brw_acc_reg(8), BRW_REGISTER_TYPE_UD);

      emit(ADDC(dst_null_ud(), op[0], op[1]));
      emit(MOV(dst, src_reg(acc)));
      break;
   }

   case nir_op_usub_borrow: {
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      struct brw_reg acc = retype(brw_acc_reg(8), BRW_REGISTER_TYPE_UD);

      emit(SUBB(dst_null_ud(), op[0], op[1]));
      emit(MOV(dst, src_reg(acc)));
      break;
   }

   case nir_op_ftrunc:
      inst = emit(RNDZ(dst, op[0]));
      if (devinfo->gen < 6) {
         inst->conditional_mod = BRW_CONDITIONAL_R;
         inst = emit(ADD(dst, src_reg(dst), brw_imm_f(1.0f)));
         inst->predicate = BRW_PREDICATE_NORMAL;
         inst = emit(MOV(dst, src_reg(dst))); /* for potential saturation */
      }
      break;

   case nir_op_fceil: {
      src_reg tmp = src_reg(this, glsl_type::float_type);
      tmp.swizzle =
         brw_swizzle_for_size(instr->src[0].src.is_ssa ?
                              instr->src[0].src.ssa->num_components :
                              instr->src[0].src.reg.reg->num_components);

      op[0].negate = !op[0].negate;
      emit(RNDD(dst_reg(tmp), op[0]));
      tmp.negate = true;
      inst = emit(MOV(dst, tmp));
      break;
   }

   case nir_op_ffloor:
      inst = emit(RNDD(dst, op[0]));
      break;

   case nir_op_ffract:
      inst = emit(FRC(dst, op[0]));
      break;

   case nir_op_fround_even:
      inst = emit(RNDE(dst, op[0]));
      if (devinfo->gen < 6) {
         inst->conditional_mod = BRW_CONDITIONAL_R;
         inst = emit(ADD(dst, src_reg(dst), brw_imm_f(1.0f)));
         inst->predicate = BRW_PREDICATE_NORMAL;
         inst = emit(MOV(dst, src_reg(dst))); /* for potential saturation */
      }
      break;

   case nir_op_fquantize2f16: {
      /* See also vec4_visitor::emit_pack_half_2x16() */
      src_reg tmp16 = src_reg(this, glsl_type::uvec4_type);
      src_reg tmp32 = src_reg(this, glsl_type::vec4_type);
      src_reg zero = src_reg(this, glsl_type::vec4_type);

      /* Check for denormal */
      src_reg abs_src0 = op[0];
      abs_src0.abs = true;
      emit(CMP(dst_null_f(), abs_src0, brw_imm_f(ldexpf(1.0, -14)),
               BRW_CONDITIONAL_L));
      /* Get the appropriately signed zero */
      emit(AND(retype(dst_reg(zero), BRW_REGISTER_TYPE_UD),
               retype(op[0], BRW_REGISTER_TYPE_UD),
               brw_imm_ud(0x80000000)));
      /* Do the actual F32 -> F16 -> F32 conversion */
      emit(F32TO16(dst_reg(tmp16), op[0]));
      emit(F16TO32(dst_reg(tmp32), tmp16));
      /* Select that or zero based on normal status */
      inst = emit(BRW_OPCODE_SEL, dst, zero, tmp32);
      inst->predicate = BRW_PREDICATE_NORMAL;
      break;
   }

   case nir_op_imin:
   case nir_op_umin:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      /* fall through */
   case nir_op_fmin:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit_minmax(BRW_CONDITIONAL_L, dst, op[0], op[1]);
      break;

   case nir_op_imax:
   case nir_op_umax:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      /* fall through */
   case nir_op_fmax:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit_minmax(BRW_CONDITIONAL_GE, dst, op[0], op[1]);
      break;

   case nir_op_fddx:
   case nir_op_fddx_coarse:
   case nir_op_fddx_fine:
   case nir_op_fddy:
   case nir_op_fddy_coarse:
   case nir_op_fddy_fine:
      unreachable("derivatives are not valid in vertex shaders");

   case nir_op_ilt32:
   case nir_op_ult32:
   case nir_op_ige32:
   case nir_op_uge32:
   case nir_op_ieq32:
   case nir_op_ine32:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      /* Fallthrough */
   case nir_op_flt32:
   case nir_op_fge32:
   case nir_op_feq32:
   case nir_op_fneu32: {
      enum brw_conditional_mod conditional_mod =
         brw_cmod_for_nir_comparison(instr->op);

      if (nir_src_bit_size(instr->src[0].src) < 64) {
         /* If the order of the sources is changed due to an immediate value,
          * then the condition must also be changed.
          */
         if (try_immediate_source(instr, op, true, devinfo) == 0)
            conditional_mod = brw_swap_cmod(conditional_mod);

         emit(CMP(dst, op[0], op[1], conditional_mod));
      } else {
         /* Produce a 32-bit boolean result from the DF comparison by selecting
          * only the low 32-bit in each DF produced. Do this in a temporary
          * so we can then move from there to the result using align16 again
          * to honor the original writemask.
          */
         dst_reg temp = dst_reg(this, glsl_type::dvec4_type);
         emit(CMP(temp, op[0], op[1], conditional_mod));
         dst_reg result = dst_reg(this, glsl_type::bvec4_type);
         emit(VEC4_OPCODE_PICK_LOW_32BIT, result, src_reg(temp));
         emit(MOV(dst, src_reg(result)));
      }
      break;
   }

   case nir_op_b32all_iequal2:
   case nir_op_b32all_iequal3:
   case nir_op_b32all_iequal4:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      /* Fallthrough */
   case nir_op_b32all_fequal2:
   case nir_op_b32all_fequal3:
   case nir_op_b32all_fequal4: {
      unsigned swiz =
         brw_swizzle_for_size(nir_op_infos[instr->op].input_sizes[0]);

      emit(CMP(dst_null_d(), swizzle(op[0], swiz), swizzle(op[1], swiz),
               brw_cmod_for_nir_comparison(instr->op)));
      emit(MOV(dst, brw_imm_d(0)));
      inst = emit(MOV(dst, brw_imm_d(~0)));
      inst->predicate = BRW_PREDICATE_ALIGN16_ALL4H;
      break;
   }

   case nir_op_b32any_inequal2:
   case nir_op_b32any_inequal3:
   case nir_op_b32any_inequal4:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      /* Fallthrough */
   case nir_op_b32any_fnequal2:
   case nir_op_b32any_fnequal3:
   case nir_op_b32any_fnequal4: {
      unsigned swiz =
         brw_swizzle_for_size(nir_op_infos[instr->op].input_sizes[0]);

      emit(CMP(dst_null_d(), swizzle(op[0], swiz), swizzle(op[1], swiz),
               brw_cmod_for_nir_comparison(instr->op)));

      emit(MOV(dst, brw_imm_d(0)));
      inst = emit(MOV(dst, brw_imm_d(~0)));
      inst->predicate = BRW_PREDICATE_ALIGN16_ANY4H;
      break;
   }

   case nir_op_inot:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      if (devinfo->gen >= 8) {
         op[0] = resolve_source_modifiers(op[0]);
      }
      emit(NOT(dst, op[0]));
      break;

   case nir_op_ixor:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      if (devinfo->gen >= 8) {
         op[0] = resolve_source_modifiers(op[0]);
         op[1] = resolve_source_modifiers(op[1]);
      }
      try_immediate_source(instr, op, true, devinfo);
      emit(XOR(dst, op[0], op[1]));
      break;

   case nir_op_ior:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      if (devinfo->gen >= 8) {
         op[0] = resolve_source_modifiers(op[0]);
         op[1] = resolve_source_modifiers(op[1]);
      }
      try_immediate_source(instr, op, true, devinfo);
      emit(OR(dst, op[0], op[1]));
      break;

   case nir_op_iand:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      if (devinfo->gen >= 8) {
         op[0] = resolve_source_modifiers(op[0]);
         op[1] = resolve_source_modifiers(op[1]);
      }
      try_immediate_source(instr, op, true, devinfo);
      emit(AND(dst, op[0], op[1]));
      break;

   case nir_op_b2i32:
   case nir_op_b2f32:
   case nir_op_b2f64:
      if (nir_dest_bit_size(instr->dest.dest) > 32) {
         assert(dst.type == BRW_REGISTER_TYPE_DF);
         emit_conversion_to_double(dst, negate(op[0]));
      } else {
         emit(MOV(dst, negate(op[0])));
      }
      break;

   case nir_op_f2b32:
      if (nir_src_bit_size(instr->src[0].src) == 64) {
         /* We use a MOV with conditional_mod to check if the provided value is
          * 0.0. We want this to flush denormalized numbers to zero, so we set a
          * source modifier on the source operand to trigger this, as source
          * modifiers don't affect the result of the testing against 0.0.
          */
         src_reg value = op[0];
         value.abs = true;
         vec4_instruction *inst = emit(MOV(dst_null_df(), value));
         inst->conditional_mod = BRW_CONDITIONAL_NZ;

         src_reg one = src_reg(this, glsl_type::ivec4_type);
         emit(MOV(dst_reg(one), brw_imm_d(~0)));
         inst = emit(BRW_OPCODE_SEL, dst, one, brw_imm_d(0));
         inst->predicate = BRW_PREDICATE_NORMAL;
      } else {
         emit(CMP(dst, op[0], brw_imm_f(0.0f), BRW_CONDITIONAL_NZ));
      }
      break;

   case nir_op_i2b32:
      emit(CMP(dst, op[0], brw_imm_d(0), BRW_CONDITIONAL_NZ));
      break;

   case nir_op_unpack_half_2x16_split_x:
   case nir_op_unpack_half_2x16_split_y:
   case nir_op_pack_half_2x16_split:
      unreachable("not reached: should not occur in vertex shader");

   case nir_op_unpack_snorm_2x16:
   case nir_op_unpack_unorm_2x16:
   case nir_op_pack_snorm_2x16:
   case nir_op_pack_unorm_2x16:
      unreachable("not reached: should be handled by lower_packing_builtins");

   case nir_op_pack_uvec4_to_uint:
      unreachable("not reached");

   case nir_op_pack_uvec2_to_uint: {
      dst_reg tmp1 = dst_reg(this, glsl_type::uint_type);
      tmp1.writemask = WRITEMASK_X;
      op[0].swizzle = BRW_SWIZZLE_YYYY;
      emit(SHL(tmp1, op[0], src_reg(brw_imm_ud(16u))));

      dst_reg tmp2 = dst_reg(this, glsl_type::uint_type);
      tmp2.writemask = WRITEMASK_X;
      op[0].swizzle = BRW_SWIZZLE_XXXX;
      emit(AND(tmp2, op[0], src_reg(brw_imm_ud(0xffffu))));

      emit(OR(dst, src_reg(tmp1), src_reg(tmp2)));
      break;
   }

   case nir_op_pack_64_2x32_split: {
      dst_reg result = dst_reg(this, glsl_type::dvec4_type);
      dst_reg tmp = dst_reg(this, glsl_type::uvec4_type);
      emit(MOV(tmp, retype(op[0], BRW_REGISTER_TYPE_UD)));
      emit(VEC4_OPCODE_SET_LOW_32BIT, result, src_reg(tmp));
      emit(MOV(tmp, retype(op[1], BRW_REGISTER_TYPE_UD)));
      emit(VEC4_OPCODE_SET_HIGH_32BIT, result, src_reg(tmp));
      emit(MOV(dst, src_reg(result)));
      break;
   }

   case nir_op_unpack_64_2x32_split_x:
   case nir_op_unpack_64_2x32_split_y: {
      enum opcode oper = (instr->op == nir_op_unpack_64_2x32_split_x) ?
         VEC4_OPCODE_PICK_LOW_32BIT : VEC4_OPCODE_PICK_HIGH_32BIT;
      dst_reg tmp = dst_reg(this, glsl_type::dvec4_type);
      emit(MOV(tmp, op[0]));
      dst_reg tmp2 = dst_reg(this, glsl_type::uvec4_type);
      emit(oper, tmp2, src_reg(tmp));
      emit(MOV(dst, src_reg(tmp2)));
      break;
   }

   case nir_op_unpack_half_2x16:
      /* As NIR does not guarantee that we have a correct swizzle outside the
       * boundaries of a vector, and the implementation of emit_unpack_half_2x16
       * uses the source operand in an operation with WRITEMASK_Y while our
       * source operand has only size 1, it accessed incorrect data producing
       * regressions in Piglit. We repeat the swizzle of the first component on the
       * rest of components to avoid regressions. In the vec4_visitor IR code path
       * this is not needed because the operand has already the correct swizzle.
       */
      op[0].swizzle = brw_compose_swizzle(BRW_SWIZZLE_XXXX, op[0].swizzle);
      emit_unpack_half_2x16(dst, op[0]);
      break;

   case nir_op_pack_half_2x16:
      emit_pack_half_2x16(dst, op[0]);
      break;

   case nir_op_unpack_unorm_4x8:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_unpack_unorm_4x8(dst, op[0]);
      break;

   case nir_op_pack_unorm_4x8:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_pack_unorm_4x8(dst, op[0]);
      break;

   case nir_op_unpack_snorm_4x8:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_unpack_snorm_4x8(dst, op[0]);
      break;

   case nir_op_pack_snorm_4x8:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_pack_snorm_4x8(dst, op[0]);
      break;

   case nir_op_bitfield_reverse:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit(BFREV(dst, op[0]));
      break;

   case nir_op_bit_count:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit(CBIT(dst, op[0]));
      break;

   case nir_op_ufind_msb:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit_find_msb_using_lzd(vec4_builder(this).at_end(), dst, op[0], false);
      break;

   case nir_op_ifind_msb: {
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      vec4_builder bld = vec4_builder(this).at_end();
      src_reg src(dst);

      if (devinfo->gen < 7) {
         emit_find_msb_using_lzd(bld, dst, op[0], true);
      } else {
         emit(FBH(retype(dst, BRW_REGISTER_TYPE_UD), op[0]));

         /* FBH counts from the MSB side, while GLSL's findMSB() wants the
          * count from the LSB side. If FBH didn't return an error
          * (0xFFFFFFFF), then subtract the result from 31 to convert the MSB
          * count into an LSB count.
          */
         bld.CMP(dst_null_d(), src, brw_imm_d(-1), BRW_CONDITIONAL_NZ);

         inst = bld.ADD(dst, src, brw_imm_d(31));
         inst->predicate = BRW_PREDICATE_NORMAL;
         inst->src[0].negate = true;
      }
      break;
   }

   case nir_op_find_lsb: {
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      vec4_builder bld = vec4_builder(this).at_end();

      if (devinfo->gen < 7) {
         dst_reg temp = bld.vgrf(BRW_REGISTER_TYPE_D);

         /* (x & -x) generates a value that consists of only the LSB of x.
          * For all powers of 2, findMSB(y) == findLSB(y).
          */
         src_reg src = src_reg(retype(op[0], BRW_REGISTER_TYPE_D));
         src_reg negated_src = src;

         /* One must be negated, and the other must be non-negated.  It
          * doesn't matter which is which.
          */
         negated_src.negate = true;
         src.negate = false;

         bld.AND(temp, src, negated_src);
         emit_find_msb_using_lzd(bld, dst, src_reg(temp), false);
      } else {
         bld.FBL(dst, op[0]);
      }
      break;
   }

   case nir_op_ubitfield_extract:
   case nir_op_ibitfield_extract:
      unreachable("should have been lowered");
   case nir_op_ubfe:
   case nir_op_ibfe:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      op[0] = fix_3src_operand(op[0]);
      op[1] = fix_3src_operand(op[1]);
      op[2] = fix_3src_operand(op[2]);

      emit(BFE(dst, op[2], op[1], op[0]));
      break;

   case nir_op_bfm:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      emit(BFI1(dst, op[0], op[1]));
      break;

   case nir_op_bfi:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      op[0] = fix_3src_operand(op[0]);
      op[1] = fix_3src_operand(op[1]);
      op[2] = fix_3src_operand(op[2]);

      emit(BFI2(dst, op[0], op[1], op[2]));
      break;

   case nir_op_bitfield_insert:
      unreachable("not reached: should have been lowered");

   case nir_op_fsign:
       if (type_sz(op[0].type) < 8) {
         /* AND(val, 0x80000000) gives the sign bit.
          *
          * Predicated OR ORs 1.0 (0x3f800000) with the sign bit if val is not
          * zero.
          */
         emit(CMP(dst_null_f(), op[0], brw_imm_f(0.0f), BRW_CONDITIONAL_NZ));

         op[0].type = BRW_REGISTER_TYPE_UD;
         dst.type = BRW_REGISTER_TYPE_UD;
         emit(AND(dst, op[0], brw_imm_ud(0x80000000u)));

         inst = emit(OR(dst, src_reg(dst), brw_imm_ud(0x3f800000u)));
         inst->predicate = BRW_PREDICATE_NORMAL;
         dst.type = BRW_REGISTER_TYPE_F;
      } else {
         /* For doubles we do the same but we need to consider:
          *
          * - We use a MOV with conditional_mod instead of a CMP so that we can
          *   skip loading a 0.0 immediate. We use a source modifier on the
          *   source of the MOV so that we flush denormalized values to 0.
          *   Since we want to compare against 0, this won't alter the result.
          * - We need to extract the high 32-bit of each DF where the sign
          *   is stored.
          * - We need to produce a DF result.
          */

         /* Check for zero */
         src_reg value = op[0];
         value.abs = true;
         inst = emit(MOV(dst_null_df(), value));
         inst->conditional_mod = BRW_CONDITIONAL_NZ;

         /* AND each high 32-bit channel with 0x80000000u */
         dst_reg tmp = dst_reg(this, glsl_type::uvec4_type);
         emit(VEC4_OPCODE_PICK_HIGH_32BIT, tmp, op[0]);
         emit(AND(tmp, src_reg(tmp), brw_imm_ud(0x80000000u)));

         /* Add 1.0 to each channel, predicated to skip the cases where the
          * channel's value was 0
          */
         inst = emit(OR(tmp, src_reg(tmp), brw_imm_ud(0x3f800000u)));
         inst->predicate = BRW_PREDICATE_NORMAL;

         /* Now convert the result from float to double */
         emit_conversion_to_double(dst, retype(src_reg(tmp),
                                               BRW_REGISTER_TYPE_F));
      }
      break;

   case nir_op_ishl:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      try_immediate_source(instr, op, false, devinfo);
      emit(SHL(dst, op[0], op[1]));
      break;

   case nir_op_ishr:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      try_immediate_source(instr, op, false, devinfo);
      emit(ASR(dst, op[0], op[1]));
      break;

   case nir_op_ushr:
      assert(nir_dest_bit_size(instr->dest.dest) < 64);
      try_immediate_source(instr, op, false, devinfo);
      emit(SHR(dst, op[0], op[1]));
      break;

   case nir_op_ffma:
      if (type_sz(dst.type) == 8) {
         dst_reg mul_dst = dst_reg(this, glsl_type::dvec4_type);
         emit(MUL(mul_dst, op[1], op[0]));
         inst = emit(ADD(dst, src_reg(mul_dst), op[2]));
      } else {
         fix_float_operands(op, instr);
         inst = emit(MAD(dst, op[2], op[1], op[0]));
      }
      break;

   case nir_op_flrp:
      fix_float_operands(op, instr);
      inst = emit(LRP(dst, op[2], op[1], op[0]));
      break;

   case nir_op_b32csel:
      enum brw_predicate predicate;
      if (!optimize_predicate(instr, &predicate)) {
         emit(CMP(dst_null_d(), op[0], brw_imm_d(0), BRW_CONDITIONAL_NZ));
         switch (dst.writemask) {
         case WRITEMASK_X:
            predicate = BRW_PREDICATE_ALIGN16_REPLICATE_X;
            break;
         case WRITEMASK_Y:
            predicate = BRW_PREDICATE_ALIGN16_REPLICATE_Y;
            break;
         case WRITEMASK_Z:
            predicate = BRW_PREDICATE_ALIGN16_REPLICATE_Z;
            break;
         case WRITEMASK_W:
            predicate = BRW_PREDICATE_ALIGN16_REPLICATE_W;
            break;
         default:
            predicate = BRW_PREDICATE_NORMAL;
            break;
         }
      }
      inst = emit(BRW_OPCODE_SEL, dst, op[1], op[2]);
      inst->predicate = predicate;
      break;

   case nir_op_fdot_replicated2:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit(BRW_OPCODE_DP2, dst, op[0], op[1]);
      break;

   case nir_op_fdot_replicated3:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit(BRW_OPCODE_DP3, dst, op[0], op[1]);
      break;

   case nir_op_fdot_replicated4:
      try_immediate_source(instr, op, true, devinfo);
      inst = emit(BRW_OPCODE_DP4, dst, op[0], op[1]);
      break;

   case nir_op_fdph_replicated:
      try_immediate_source(instr, op, false, devinfo);
      inst = emit(BRW_OPCODE_DPH, dst, op[0], op[1]);
      break;

   case nir_op_fdiv:
      unreachable("not reached: should be lowered by DIV_TO_MUL_RCP in the compiler");

   case nir_op_fmod:
      unreachable("not reached: should be lowered by MOD_TO_FLOOR in the compiler");

   case nir_op_fsub:
   case nir_op_isub:
      unreachable("not reached: should be handled by ir_sub_to_add_neg");

   default:
      unreachable("Unimplemented ALU operation");
   }

   /* If we need to do a boolean resolve, replace the result with -(x & 1)
    * to sign extend the low bit to 0/~0
    */
   if (devinfo->gen <= 5 &&
       (instr->instr.pass_flags & BRW_NIR_BOOLEAN_MASK) ==
       BRW_NIR_BOOLEAN_NEEDS_RESOLVE) {
      dst_reg masked = dst_reg(this, glsl_type::int_type);
      masked.writemask = dst.writemask;
      emit(AND(masked, src_reg(dst), brw_imm_d(1)));
      src_reg masked_neg = src_reg(masked);
      masked_neg.negate = true;
      emit(MOV(retype(dst, BRW_REGISTER_TYPE_D), masked_neg));
   }
}

void
vec4_visitor::nir_emit_jump(nir_jump_instr *instr)
{
   switch (instr->type) {
   case nir_jump_break:
      emit(BRW_OPCODE_BREAK);
      break;

   case nir_jump_continue:
      emit(BRW_OPCODE_CONTINUE);
      break;

   case nir_jump_return:
      /* fall through */
   default:
      unreachable("unknown jump");
   }
}

static enum ir_texture_opcode
ir_texture_opcode_for_nir_texop(nir_texop texop)
{
   enum ir_texture_opcode op;

   switch (texop) {
   case nir_texop_lod: op = ir_lod; break;
   case nir_texop_query_levels: op = ir_query_levels; break;
   case nir_texop_texture_samples: op = ir_texture_samples; break;
   case nir_texop_tex: op = ir_tex; break;
   case nir_texop_tg4: op = ir_tg4; break;
   case nir_texop_txb: op = ir_txb; break;
   case nir_texop_txd: op = ir_txd; break;
   case nir_texop_txf: op = ir_txf; break;
   case nir_texop_txf_ms: op = ir_txf_ms; break;
   case nir_texop_txl: op = ir_txl; break;
   case nir_texop_txs: op = ir_txs; break;
   case nir_texop_samples_identical: op = ir_samples_identical; break;
   default:
      unreachable("unknown texture opcode");
   }

   return op;
}

static const glsl_type *
glsl_type_for_nir_alu_type(nir_alu_type alu_type,
                           unsigned components)
{
   return glsl_type::get_instance(brw_glsl_base_type_for_nir_type(alu_type),
                                  components, 1);
}

void
vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
{
   unsigned texture = instr->texture_index;
   unsigned sampler = instr->sampler_index;
   src_reg texture_reg = brw_imm_ud(texture);
   src_reg sampler_reg = brw_imm_ud(sampler);
   src_reg coordinate;
   const glsl_type *coord_type = NULL;
   src_reg shadow_comparator;
   src_reg offset_value;
   src_reg lod, lod2;
   src_reg sample_index;
   src_reg mcs;

   const glsl_type *dest_type =
      glsl_type_for_nir_alu_type(instr->dest_type,
                                 nir_tex_instr_dest_size(instr));
   dst_reg dest = get_nir_dest(instr->dest, instr->dest_type);

   /* The hardware requires a LOD for buffer textures */
   if (instr->sampler_dim == GLSL_SAMPLER_DIM_BUF)
      lod = brw_imm_d(0);

   /* Load the texture operation sources */
   uint32_t constant_offset = 0;
   for (unsigned i = 0; i < instr->num_srcs; i++) {
      switch (instr->src[i].src_type) {
      case nir_tex_src_comparator:
         shadow_comparator = get_nir_src(instr->src[i].src,
                                         BRW_REGISTER_TYPE_F, 1);
         break;

      case nir_tex_src_coord: {
         unsigned src_size = nir_tex_instr_src_size(instr, i);

         switch (instr->op) {
         case nir_texop_txf:
         case nir_texop_txf_ms:
         case nir_texop_samples_identical:
            coordinate = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D,
                                     src_size);
            coord_type = glsl_type::ivec(src_size);
            break;

         default:
            coordinate = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F,
                                     src_size);
            coord_type = glsl_type::vec(src_size);
            break;
         }
         break;
      }

      case nir_tex_src_ddx:
         lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F,
                           nir_tex_instr_src_size(instr, i));
         break;

      case nir_tex_src_ddy:
         lod2 = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F,
                           nir_tex_instr_src_size(instr, i));
         break;

      case nir_tex_src_lod:
         switch (instr->op) {
         case nir_texop_txs:
         case nir_texop_txf:
            lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 1);
            break;

         default:
            lod = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_F, 1);
            break;
         }
         break;

      case nir_tex_src_ms_index: {
         sample_index = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 1);
         break;
      }

      case nir_tex_src_offset:
         if (!brw_texture_offset(instr, i, &constant_offset)) {
            offset_value =
               get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 2);
         }
         break;

      case nir_tex_src_texture_offset: {
         /* Emit code to evaluate the actual indexing expression */
         src_reg src = get_nir_src(instr->src[i].src, 1);
         src_reg temp(this, glsl_type::uint_type);
         emit(ADD(dst_reg(temp), src, brw_imm_ud(texture)));
         texture_reg = emit_uniformize(temp);
         break;
      }

      case nir_tex_src_sampler_offset: {
         /* Emit code to evaluate the actual indexing expression */
         src_reg src = get_nir_src(instr->src[i].src, 1);
         src_reg temp(this, glsl_type::uint_type);
         emit(ADD(dst_reg(temp), src, brw_imm_ud(sampler)));
         sampler_reg = emit_uniformize(temp);
         break;
      }

      case nir_tex_src_projector:
         unreachable("Should be lowered by do_lower_texture_projection");

      case nir_tex_src_bias:
         unreachable("LOD bias is not valid for vertex shaders.\n");

      default:
         unreachable("unknown texture source");
      }
   }

   if (instr->op == nir_texop_txf_ms ||
       instr->op == nir_texop_samples_identical) {
      assert(coord_type != NULL);
      if (devinfo->gen >= 7 &&
          key_tex->compressed_multisample_layout_mask & (1 << texture)) {
         mcs = emit_mcs_fetch(coord_type, coordinate, texture_reg);
      } else {
         mcs = brw_imm_ud(0u);
      }
   }

   /* Stuff the channel select bits in the top of the texture offset */
   if (instr->op == nir_texop_tg4) {
      if (instr->component == 1 &&
          (key_tex->gather_channel_quirk_mask & (1 << texture))) {
         /* gather4 sampler is broken for green channel on RG32F --
          * we must ask for blue instead.
          */
         constant_offset |= 2 << 16;
      } else {
         constant_offset |= instr->component << 16;
      }
   }

   ir_texture_opcode op = ir_texture_opcode_for_nir_texop(instr->op);

   emit_texture(op, dest, dest_type, coordinate, instr->coord_components,
                shadow_comparator,
                lod, lod2, sample_index,
                constant_offset, offset_value, mcs,
                texture, texture_reg, sampler_reg);
}

void
vec4_visitor::nir_emit_undef(nir_ssa_undef_instr *instr)
{
   nir_ssa_values[instr->def.index] =
      dst_reg(VGRF, alloc.allocate(DIV_ROUND_UP(instr->def.bit_size, 32)));
}

/* SIMD4x2 64bit data is stored in register space like this:
 *
 * r0.0:DF  x0 y0 z0 w0
 * r1.0:DF  x1 y1 z1 w1
 *
 * When we need to write data such as this to memory using 32-bit write
 * messages we need to shuffle it in this fashion:
 *
 * r0.0:DF  x0 y0 x1 y1 (to be written at base offset)
 * r0.0:DF  z0 w0 z1 w1 (to be written at base offset + 16)
 *
 * We need to do the inverse operation when we read using 32-bit messages,
 * which we can do by applying the same exact shuffling on the 64-bit data
 * read, only that because the data for each vertex is positioned differently
 * we need to apply different channel enables.
 *
 * This function takes 64bit data and shuffles it as explained above.
 *
 * The @for_write parameter is used to specify if the shuffling is being done
 * for proper SIMD4x2 64-bit data that needs to be shuffled prior to a 32-bit
 * write message (for_write = true), or instead we are doing the inverse
 * operation and we have just read 64-bit data using a 32-bit messages that we
 * need to shuffle to create valid SIMD4x2 64-bit data (for_write = false).
 *
 * If @block and @ref are non-NULL, then the shuffling is done after @ref,
 * otherwise the instructions are emitted normally at the end. The function
 * returns the last instruction inserted.
 *
 * Notice that @src and @dst cannot be the same register.
 */
vec4_instruction *
vec4_visitor::shuffle_64bit_data(dst_reg dst, src_reg src, bool for_write,
                                 bblock_t *block, vec4_instruction *ref)
{
   assert(type_sz(src.type) == 8);
   assert(type_sz(dst.type) == 8);
   assert(!regions_overlap(dst, 2 * REG_SIZE, src, 2 * REG_SIZE));
   assert(!ref == !block);

   const vec4_builder bld = !ref ? vec4_builder(this).at_end() :
                                   vec4_builder(this).at(block, ref->next);

   /* Resolve swizzle in src */
   vec4_instruction *inst;
   if (src.swizzle != BRW_SWIZZLE_XYZW) {
      dst_reg data = dst_reg(this, glsl_type::dvec4_type);
      inst = bld.MOV(data, src);
      src = src_reg(data);
   }

   /* dst+0.XY = src+0.XY */
   inst = bld.group(4, 0).MOV(writemask(dst, WRITEMASK_XY), src);

   /* dst+0.ZW = src+1.XY */
   inst = bld.group(4, for_write ? 1 : 0)
             .MOV(writemask(dst, WRITEMASK_ZW),
                  swizzle(byte_offset(src, REG_SIZE), BRW_SWIZZLE_XYXY));

   /* dst+1.XY = src+0.ZW */
   inst = bld.group(4, for_write ? 0 : 1)
            .MOV(writemask(byte_offset(dst, REG_SIZE), WRITEMASK_XY),
                 swizzle(src, BRW_SWIZZLE_ZWZW));

   /* dst+1.ZW = src+1.ZW */
   inst = bld.group(4, 1)
             .MOV(writemask(byte_offset(dst, REG_SIZE), WRITEMASK_ZW),
                 byte_offset(src, REG_SIZE));

   return inst;
}

}
