i965/fs: Fix gl_SampleID for 2x MSAA and SIMD16 mode.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs.cpp
index 713e47761d016e8626643c879a0b30faec9fec9e..0d1185b5e07172d139787ef3199bf84d9f0d742c 100644 (file)
@@ -52,108 +52,108 @@ extern "C" {
 #include "glsl/glsl_types.h"
 
 void
-fs_inst::init()
+fs_inst::init(enum opcode opcode, const fs_reg &dst, fs_reg *src, int sources)
 {
    memset(this, 0, sizeof(*this));
-   this->conditional_mod = BRW_CONDITIONAL_NONE;
 
-   this->dst = reg_undef;
-   this->src[0] = reg_undef;
-   this->src[1] = reg_undef;
-   this->src[2] = reg_undef;
+   this->opcode = opcode;
+   this->dst = dst;
+   this->src = src;
+   this->sources = sources;
+
+   this->conditional_mod = BRW_CONDITIONAL_NONE;
 
    /* This will be the case for almost all instructions. */
    this->regs_written = 1;
+
+   this->writes_accumulator = false;
 }
 
-fs_inst::fs_inst()
+fs_inst::fs_inst(enum opcode opcode, const fs_reg &dst)
 {
-   init();
-   this->opcode = BRW_OPCODE_NOP;
+   fs_reg *src = ralloc_array(this, fs_reg, 3);
+   init(opcode, dst, src, 0);
 }
 
-fs_inst::fs_inst(enum opcode opcode)
+fs_inst::fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg &src0)
 {
-   init();
-   this->opcode = opcode;
+   fs_reg *src = ralloc_array(this, fs_reg, 3);
+   src[0] = src0;
+   init(opcode, dst, src, 1);
 }
 
-fs_inst::fs_inst(enum opcode opcode, fs_reg dst)
+fs_inst::fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg &src0,
+                 const fs_reg &src1)
 {
-   init();
-   this->opcode = opcode;
-   this->dst = dst;
-
-   if (dst.file == GRF)
-      assert(dst.reg_offset >= 0);
+   fs_reg *src = ralloc_array(this, fs_reg, 3);
+   src[0] = src0;
+   src[1] = src1;
+   init(opcode, dst, src, 2);
 }
 
-fs_inst::fs_inst(enum opcode opcode, fs_reg dst, fs_reg src0)
+fs_inst::fs_inst(enum opcode opcode, const fs_reg &dst, const fs_reg &src0,
+                 const fs_reg &src1, const fs_reg &src2)
 {
-   init();
-   this->opcode = opcode;
-   this->dst = dst;
-   this->src[0] = src0;
+   fs_reg *src = ralloc_array(this, fs_reg, 3);
+   src[0] = src0;
+   src[1] = src1;
+   src[2] = src2;
+   init(opcode, dst, src, 3);
+}
 
-   if (dst.file == GRF)
-      assert(dst.reg_offset >= 0);
-   if (src[0].file == GRF)
-      assert(src[0].reg_offset >= 0);
+fs_inst::fs_inst(enum opcode opcode, const fs_reg &dst, fs_reg src[], int sources)
+{
+   init(opcode, dst, src, sources);
 }
 
-fs_inst::fs_inst(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1)
+fs_inst::fs_inst(const fs_inst &that)
 {
-   init();
-   this->opcode = opcode;
-   this->dst = dst;
-   this->src[0] = src0;
-   this->src[1] = src1;
+   memcpy(this, &that, sizeof(that));
 
-   if (dst.file == GRF)
-      assert(dst.reg_offset >= 0);
-   if (src[0].file == GRF)
-      assert(src[0].reg_offset >= 0);
-   if (src[1].file == GRF)
-      assert(src[1].reg_offset >= 0);
+   this->src = ralloc_array(this, fs_reg, that.sources);
+
+   for (int i = 0; i < that.sources; i++)
+      this->src[i] = that.src[i];
 }
 
-fs_inst::fs_inst(enum opcode opcode, fs_reg dst,
-                fs_reg src0, fs_reg src1, fs_reg src2)
+void
+fs_inst::resize_sources(uint8_t num_sources)
 {
-   init();
-   this->opcode = opcode;
-   this->dst = dst;
-   this->src[0] = src0;
-   this->src[1] = src1;
-   this->src[2] = src2;
-
-   if (dst.file == GRF)
-      assert(dst.reg_offset >= 0);
-   if (src[0].file == GRF)
-      assert(src[0].reg_offset >= 0);
-   if (src[1].file == GRF)
-      assert(src[1].reg_offset >= 0);
-   if (src[2].file == GRF)
-      assert(src[2].reg_offset >= 0);
+   if (this->sources != num_sources) {
+      this->src = reralloc(this, this->src, fs_reg, num_sources);
+      this->sources = num_sources;
+   }
 }
 
 #define ALU1(op)                                                        \
    fs_inst *                                                            \
-   fs_visitor::op(fs_reg dst, fs_reg src0)                              \
+   fs_visitor::op(const fs_reg &dst, const fs_reg &src0)                \
    {                                                                    \
       return new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0);          \
    }
 
 #define ALU2(op)                                                        \
    fs_inst *                                                            \
-   fs_visitor::op(fs_reg dst, fs_reg src0, fs_reg src1)                 \
+   fs_visitor::op(const fs_reg &dst, const fs_reg &src0,                \
+                  const fs_reg &src1)                                   \
    {                                                                    \
       return new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0, src1);    \
    }
 
+#define ALU2_ACC(op)                                                    \
+   fs_inst *                                                            \
+   fs_visitor::op(const fs_reg &dst, const fs_reg &src0,                \
+                  const fs_reg &src1)                                   \
+   {                                                                    \
+      fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0, src1);\
+      inst->writes_accumulator = true;                                  \
+      return inst;                                                      \
+   }
+
 #define ALU3(op)                                                        \
    fs_inst *                                                            \
-   fs_visitor::op(fs_reg dst, fs_reg src0, fs_reg src1, fs_reg src2)    \
+   fs_visitor::op(const fs_reg &dst, const fs_reg &src0,                \
+                  const fs_reg &src1, const fs_reg &src2)               \
    {                                                                    \
       return new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0, src1, src2);\
    }
@@ -166,7 +166,7 @@ ALU1(RNDE)
 ALU1(RNDZ)
 ALU2(ADD)
 ALU2(MUL)
-ALU2(MACH)
+ALU2_ACC(MACH)
 ALU2(AND)
 ALU2(OR)
 ALU2(XOR)
@@ -182,13 +182,14 @@ ALU1(FBH)
 ALU1(FBL)
 ALU1(CBIT)
 ALU3(MAD)
-ALU2(ADDC)
-ALU2(SUBB)
+ALU2_ACC(ADDC)
+ALU2_ACC(SUBB)
 ALU2(SEL)
+ALU2(MAC)
 
 /** Gen4 predicated IF. */
 fs_inst *
-fs_visitor::IF(uint32_t predicate)
+fs_visitor::IF(enum brw_predicate predicate)
 {
    fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_IF);
    inst->predicate = predicate;
@@ -197,7 +198,8 @@ fs_visitor::IF(uint32_t predicate)
 
 /** Gen6 IF with embedded comparison. */
 fs_inst *
-fs_visitor::IF(fs_reg src0, fs_reg src1, uint32_t condition)
+fs_visitor::IF(const fs_reg &src0, const fs_reg &src1,
+               enum brw_conditional_mod condition)
 {
    assert(brw->gen == 6);
    fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_IF,
@@ -212,7 +214,8 @@ fs_visitor::IF(fs_reg src0, fs_reg src1, uint32_t condition)
  * the flag register with the packed 16 bits of the result.
  */
 fs_inst *
-fs_visitor::CMP(fs_reg dst, fs_reg src0, fs_reg src1, uint32_t condition)
+fs_visitor::CMP(fs_reg dst, fs_reg src0, fs_reg src1,
+                enum brw_conditional_mod condition)
 {
    fs_inst *inst;
 
@@ -243,6 +246,16 @@ fs_visitor::CMP(fs_reg dst, fs_reg src0, fs_reg src1, uint32_t condition)
    return inst;
 }
 
+fs_inst *
+fs_visitor::LOAD_PAYLOAD(const fs_reg &dst, fs_reg *src, int sources)
+{
+   fs_inst *inst = new(mem_ctx) fs_inst(SHADER_OPCODE_LOAD_PAYLOAD, dst, src,
+                                        sources);
+   inst->regs_written = sources;
+
+   return inst;
+}
+
 exec_list
 fs_visitor::VARYING_PULL_CONSTANT_LOAD(const fs_reg &dst,
                                        const fs_reg &surf_index,
@@ -323,7 +336,7 @@ fs_visitor::DEP_RESOLVE_MOV(int grf)
 }
 
 bool
-fs_inst::equals(fs_inst *inst)
+fs_inst::equals(fs_inst *inst) const
 {
    return (opcode == inst->opcode &&
            dst.equals(inst->dst) &&
@@ -344,7 +357,7 @@ fs_inst::equals(fs_inst *inst)
 }
 
 bool
-fs_inst::overwrites_reg(const fs_reg &reg)
+fs_inst::overwrites_reg(const fs_reg &reg) const
 {
    return (reg.file == dst.file &&
            reg.reg == dst.reg &&
@@ -353,25 +366,29 @@ fs_inst::overwrites_reg(const fs_reg &reg)
 }
 
 bool
-fs_inst::is_send_from_grf()
+fs_inst::is_send_from_grf() const
 {
    return (opcode == FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7 ||
            opcode == SHADER_OPCODE_SHADER_TIME_ADD ||
+           opcode == FS_OPCODE_INTERPOLATE_AT_CENTROID ||
+           opcode == FS_OPCODE_INTERPOLATE_AT_SAMPLE ||
+           opcode == FS_OPCODE_INTERPOLATE_AT_SHARED_OFFSET ||
+           opcode == FS_OPCODE_INTERPOLATE_AT_PER_SLOT_OFFSET ||
            (opcode == FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD &&
             src[1].file == GRF) ||
            (is_tex() && src[0].file == GRF));
 }
 
 bool
-fs_visitor::can_do_source_mods(fs_inst *inst)
+fs_inst::can_do_source_mods(struct brw_context *brw)
 {
-   if (brw->gen == 6 && inst->is_math())
+   if (brw->gen == 6 && is_math())
       return false;
 
-   if (inst->is_send_from_grf())
+   if (is_send_from_grf())
       return false;
 
-   if (!inst->can_do_source_mods())
+   if (!backend_instruction::can_do_source_mods())
       return false;
 
    return true;
@@ -397,7 +414,7 @@ fs_reg::fs_reg(float f)
    init();
    this->file = IMM;
    this->type = BRW_REGISTER_TYPE_F;
-   this->imm.f = f;
+   this->fixed_hw_reg.dw1.f = f;
 }
 
 /** Immediate value constructor. */
@@ -406,7 +423,7 @@ fs_reg::fs_reg(int32_t i)
    init();
    this->file = IMM;
    this->type = BRW_REGISTER_TYPE_D;
-   this->imm.i = i;
+   this->fixed_hw_reg.dw1.d = i;
 }
 
 /** Immediate value constructor. */
@@ -415,7 +432,7 @@ fs_reg::fs_reg(uint32_t u)
    init();
    this->file = IMM;
    this->type = BRW_REGISTER_TYPE_UD;
-   this->imm.u = u;
+   this->fixed_hw_reg.dw1.ud = u;
 }
 
 /** Fixed brw_reg. */
@@ -440,8 +457,7 @@ fs_reg::equals(const fs_reg &r) const
            !reladdr && !r.reladdr &&
            memcmp(&fixed_hw_reg, &r.fixed_hw_reg,
                   sizeof(fixed_hw_reg)) == 0 &&
-           stride == r.stride &&
-           imm.u == r.imm.u);
+           stride == r.stride);
 }
 
 fs_reg &
@@ -469,32 +485,6 @@ fs_reg::is_contiguous() const
    return stride == 1;
 }
 
-bool
-fs_reg::is_zero() const
-{
-   if (file != IMM)
-      return false;
-
-   return type == BRW_REGISTER_TYPE_F ? imm.f == 0.0 : imm.i == 0;
-}
-
-bool
-fs_reg::is_one() const
-{
-   if (file != IMM)
-      return false;
-
-   return type == BRW_REGISTER_TYPE_F ? imm.f == 1.0 : imm.i == 1;
-}
-
-bool
-fs_reg::is_null() const
-{
-   return file == HW_REG &&
-          fixed_hw_reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
-          fixed_hw_reg.nr == BRW_ARF_NULL;
-}
-
 bool
 fs_reg::is_valid_3src() const
 {
@@ -531,8 +521,7 @@ fs_visitor::type_size(const struct glsl_type *type)
    case GLSL_TYPE_VOID:
    case GLSL_TYPE_ERROR:
    case GLSL_TYPE_INTERFACE:
-      assert(!"not reached");
-      break;
+      unreachable("not reached");
    }
 
    return 0;
@@ -697,7 +686,7 @@ fs_visitor::no16(const char *format, ...)
    } else {
       simd16_unsupported = true;
 
-      if (INTEL_DEBUG & DEBUG_PERF) {
+      if (brw->perf_debug) {
          if (no16_msg)
             ralloc_vasprintf_append(&no16_msg, format, va);
          else
@@ -715,30 +704,38 @@ fs_visitor::emit(enum opcode opcode)
 }
 
 fs_inst *
-fs_visitor::emit(enum opcode opcode, fs_reg dst)
+fs_visitor::emit(enum opcode opcode, const fs_reg &dst)
 {
    return emit(new(mem_ctx) fs_inst(opcode, dst));
 }
 
 fs_inst *
-fs_visitor::emit(enum opcode opcode, fs_reg dst, fs_reg src0)
+fs_visitor::emit(enum opcode opcode, const fs_reg &dst, const fs_reg &src0)
 {
    return emit(new(mem_ctx) fs_inst(opcode, dst, src0));
 }
 
 fs_inst *
-fs_visitor::emit(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1)
+fs_visitor::emit(enum opcode opcode, const fs_reg &dst, const fs_reg &src0,
+                 const fs_reg &src1)
 {
    return emit(new(mem_ctx) fs_inst(opcode, dst, src0, src1));
 }
 
 fs_inst *
-fs_visitor::emit(enum opcode opcode, fs_reg dst,
-                 fs_reg src0, fs_reg src1, fs_reg src2)
+fs_visitor::emit(enum opcode opcode, const fs_reg &dst, const fs_reg &src0,
+                 const fs_reg &src1, const fs_reg &src2)
 {
    return emit(new(mem_ctx) fs_inst(opcode, dst, src0, src1, src2));
 }
 
+fs_inst *
+fs_visitor::emit(enum opcode opcode, const fs_reg &dst,
+                 fs_reg src[], int sources)
+{
+   return emit(new(mem_ctx) fs_inst(opcode, dst, src, sources));
+}
+
 void
 fs_visitor::push_force_uncompressed()
 {
@@ -761,7 +758,7 @@ fs_visitor::pop_force_uncompressed()
  * it.
  */
 bool
-fs_inst::is_partial_write()
+fs_inst::is_partial_write() const
 {
    return ((this->predicate && this->opcode != BRW_OPCODE_SEL) ||
            this->force_uncompressed ||
@@ -769,7 +766,7 @@ fs_inst::is_partial_write()
 }
 
 int
-fs_inst::regs_read(fs_visitor *v, int arg)
+fs_inst::regs_read(fs_visitor *v, int arg) const
 {
    if (is_tex() && arg == 0 && src[0].file == GRF) {
       if (v->dispatch_width == 16)
@@ -781,13 +778,13 @@ fs_inst::regs_read(fs_visitor *v, int arg)
 }
 
 bool
-fs_inst::reads_flag()
+fs_inst::reads_flag() const
 {
    return predicate;
 }
 
 bool
-fs_inst::writes_flag()
+fs_inst::writes_flag() const
 {
    return (conditional_mod && opcode != BRW_OPCODE_SEL) ||
           opcode == FS_OPCODE_MOV_DISPATCH_TO_FLAGS;
@@ -844,10 +841,13 @@ fs_visitor::implied_mrf_writes(fs_inst *inst)
       return 2;
    case SHADER_OPCODE_UNTYPED_ATOMIC:
    case SHADER_OPCODE_UNTYPED_SURFACE_READ:
+   case FS_OPCODE_INTERPOLATE_AT_CENTROID:
+   case FS_OPCODE_INTERPOLATE_AT_SAMPLE:
+   case FS_OPCODE_INTERPOLATE_AT_SHARED_OFFSET:
+   case FS_OPCODE_INTERPOLATE_AT_PER_SLOT_OFFSET:
       return 0;
    default:
-      assert(!"not reached");
-      return inst->mlen;
+      unreachable("not reached");
    }
 }
 
@@ -876,7 +876,7 @@ fs_reg::fs_reg(enum register_file file, int reg)
 }
 
 /** Fixed HW reg constructor. */
-fs_reg::fs_reg(enum register_file file, int reg, uint32_t type)
+fs_reg::fs_reg(enum register_file file, int reg, enum brw_reg_type type)
 {
    init();
    this->file = file;
@@ -1011,7 +1011,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
 {
    fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
    fs_reg wpos = *reg;
-   bool flip = !ir->data.origin_upper_left ^ c->key.render_to_fbo;
+   bool flip = !ir->data.origin_upper_left ^ key->render_to_fbo;
 
    /* gl_FragCoord.x */
    if (ir->data.pixel_center_integer) {
@@ -1030,7 +1030,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
 
       if (flip) {
         pixel_y.negate = true;
-        offset += c->key.drawable_height - 1.0;
+        offset += key->drawable_height - 1.0;
       }
 
       emit(ADD(wpos, pixel_y, fs_reg(offset)));
@@ -1039,7 +1039,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
 
    /* gl_FragCoord.z */
    if (brw->gen >= 6) {
-      emit(MOV(wpos, fs_reg(brw_vec8_grf(c->source_depth_reg, 0))));
+      emit(MOV(wpos, fs_reg(brw_vec8_grf(payload.source_depth_reg, 0))));
    } else {
       emit(FS_OPCODE_LINTERP, wpos,
            this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC],
@@ -1111,12 +1111,12 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
    }
 
    glsl_interp_qualifier interpolation_mode =
-      ir->determine_interpolation_mode(c->key.flat_shade);
+      ir->determine_interpolation_mode(key->flat_shade);
 
    int location = ir->data.location;
    for (unsigned int i = 0; i < array_elements; i++) {
       for (unsigned int j = 0; j < type->matrix_columns; j++) {
-        if (c->prog_data.urb_setup[location] == -1) {
+        if (prog_data->urb_setup[location] == -1) {
            /* If there's no incoming setup data for this slot, don't
             * emit interpolation for it.
             */
@@ -1141,9 +1141,6 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
            /* Smooth/noperspective interpolation case. */
            for (unsigned int k = 0; k < type->vector_elements; k++) {
                struct brw_reg interp = interp_reg(location, k);
-               emit_linterp(attr, fs_reg(interp), interpolation_mode,
-                            ir->data.centroid && !c->key.persample_shading,
-                            ir->data.sample || c->key.persample_shading);
                if (brw->needs_unlit_centroid_workaround && ir->data.centroid) {
                   /* Get the pixel/sample mask into f0 so that we know
                    * which pixels are lit.  Then, for each channel that is
@@ -1151,11 +1148,27 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
                    * data.
                    */
                   emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS);
-                  fs_inst *inst = emit_linterp(attr, fs_reg(interp),
-                                               interpolation_mode,
-                                               false, false);
+
+                  fs_inst *inst;
+                  inst = emit_linterp(attr, fs_reg(interp), interpolation_mode,
+                                      false, false);
                   inst->predicate = BRW_PREDICATE_NORMAL;
                   inst->predicate_inverse = true;
+                  if (brw->has_pln)
+                     inst->no_dd_clear = true;
+
+                  inst = emit_linterp(attr, fs_reg(interp), interpolation_mode,
+                                      ir->data.centroid && !key->persample_shading,
+                                      ir->data.sample || key->persample_shading);
+                  inst->predicate = BRW_PREDICATE_NORMAL;
+                  inst->predicate_inverse = false;
+                  if (brw->has_pln)
+                     inst->no_dd_check = true;
+
+               } else {
+                  emit_linterp(attr, fs_reg(interp), interpolation_mode,
+                               ir->data.centroid && !key->persample_shading,
+                               ir->data.sample || key->persample_shading);
                }
                if (brw->gen < 6 && interpolation_mode == INTERP_QUALIFIER_SMOOTH) {
                   emit(BRW_OPCODE_MUL, attr, attr, this->pixel_w);
@@ -1200,7 +1213,7 @@ fs_visitor::compute_sample_position(fs_reg dst, fs_reg int_sample_pos)
 {
    assert(dst.type == BRW_REGISTER_TYPE_F);
 
-   if (c->key.compute_pos_offset) {
+   if (key->compute_pos_offset) {
       /* Convert int_sample_pos to floating point */
       emit(MOV(dst, int_sample_pos));
       /* Scale to the range [0, 1] */
@@ -1240,22 +1253,24 @@ fs_visitor::emit_samplepos_setup(ir_variable *ir)
     * the positions using vstride=16, width=8, hstride=2.
     */
    struct brw_reg sample_pos_reg =
-      stride(retype(brw_vec1_grf(c->sample_pos_reg, 0),
+      stride(retype(brw_vec1_grf(payload.sample_pos_reg, 0),
                     BRW_REGISTER_TYPE_B), 16, 8, 2);
 
-   emit(MOV(int_sample_x, fs_reg(sample_pos_reg)));
+   fs_inst *inst = emit(MOV(int_sample_x, fs_reg(sample_pos_reg)));
    if (dispatch_width == 16) {
-      fs_inst *inst = emit(MOV(half(int_sample_x, 1),
-                               fs_reg(suboffset(sample_pos_reg, 16))));
+      inst->force_uncompressed = true;
+      inst = emit(MOV(half(int_sample_x, 1),
+                      fs_reg(suboffset(sample_pos_reg, 16))));
       inst->force_sechalf = true;
    }
    /* Compute gl_SamplePosition.x */
    compute_sample_position(pos, int_sample_x);
    pos.reg_offset++;
-   emit(MOV(int_sample_y, fs_reg(suboffset(sample_pos_reg, 1))));
+   inst = emit(MOV(int_sample_y, fs_reg(suboffset(sample_pos_reg, 1))));
    if (dispatch_width == 16) {
-      fs_inst *inst = emit(MOV(half(int_sample_y, 1),
-                               fs_reg(suboffset(sample_pos_reg, 17))));
+      inst->force_uncompressed = true;
+      inst = emit(MOV(half(int_sample_y, 1),
+                      fs_reg(suboffset(sample_pos_reg, 17))));
       inst->force_sechalf = true;
    }
    /* Compute gl_SamplePosition.y */
@@ -1271,7 +1286,7 @@ fs_visitor::emit_sampleid_setup(ir_variable *ir)
    this->current_annotation = "compute sample id";
    fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
 
-   if (c->key.compute_sample_id) {
+   if (key->compute_sample_id) {
       fs_reg t1 = fs_reg(this, glsl_type::int_type);
       fs_reg t2 = fs_reg(this, glsl_type::int_type);
       t2.type = BRW_REGISTER_TYPE_UW;
@@ -1289,13 +1304,22 @@ fs_visitor::emit_sampleid_setup(ir_variable *ir)
        * populating a temporary variable with the sequence (0, 1, 2, 3),
        * and then reading from it using vstride=1, width=4, hstride=0.
        * These computations hold good for 4x multisampling as well.
+       *
+       * For 2x MSAA and SIMD16, we want to use the sequence (0, 1, 0, 1):
+       * the first four slots are sample 0 of subspan 0; the next four
+       * are sample 1 of subspan 0; the third group is sample 0 of
+       * subspan 1, and finally sample 1 of subspan 1.
        */
-      emit(BRW_OPCODE_AND, t1,
-           fs_reg(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_D)),
-           fs_reg(brw_imm_d(0xc0)));
-      emit(BRW_OPCODE_SHR, t1, t1, fs_reg(5));
+      fs_inst *inst;
+      inst = emit(BRW_OPCODE_AND, t1,
+                  fs_reg(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UD)),
+                  fs_reg(0xc0));
+      inst->force_writemask_all = true;
+      inst = emit(BRW_OPCODE_SHR, t1, t1, fs_reg(5));
+      inst->force_writemask_all = true;
       /* This works for both SIMD8 and SIMD16 */
-      emit(MOV(t2, brw_imm_v(0x3210)));
+      inst = emit(MOV(t2, brw_imm_v(key->persample_2x ? 0x1010 : 0x3210)));
+      inst->force_writemask_all = true;
       /* This special instruction takes care of setting vstride=1,
        * width=4, hstride=0 of t2 during an ADD instruction.
        */
@@ -1311,16 +1335,6 @@ fs_visitor::emit_sampleid_setup(ir_variable *ir)
    return reg;
 }
 
-fs_reg *
-fs_visitor::emit_samplemaskin_setup(ir_variable *ir)
-{
-   assert(brw->gen >= 7);
-   this->current_annotation = "compute gl_SampleMaskIn";
-   fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
-   emit(MOV(*reg, fs_reg(retype(brw_vec8_grf(c->sample_mask_reg, 0), BRW_REGISTER_TYPE_D))));
-   return reg;
-}
-
 fs_reg
 fs_visitor::fix_math_operand(fs_reg src)
 {
@@ -1361,8 +1375,7 @@ fs_visitor::emit_math(enum opcode opcode, fs_reg dst, fs_reg src)
    case SHADER_OPCODE_COS:
       break;
    default:
-      assert(!"not reached: bad math opcode");
-      return NULL;
+      unreachable("not reached: bad math opcode");
    }
 
    /* Can't do hstride == 0 args to gen6 math, so expand it out.  We
@@ -1373,7 +1386,7 @@ fs_visitor::emit_math(enum opcode opcode, fs_reg dst, fs_reg src)
     * Gen 6 hardware ignores source modifiers (negate and abs) on math
     * instructions, so we also move to a temp to set those up.
     */
-   if (brw->gen >= 6)
+   if (brw->gen == 6 || brw->gen == 7)
       src = fix_math_operand(src);
 
    fs_inst *inst = emit(opcode, dst, src);
@@ -1401,11 +1414,12 @@ fs_visitor::emit_math(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1)
    case SHADER_OPCODE_POW:
       break;
    default:
-      assert(!"not reached: unsupported binary math opcode.");
-      return NULL;
+      unreachable("not reached: unsupported binary math opcode.");
    }
 
-   if (brw->gen >= 6) {
+   if (brw->gen >= 8) {
+      inst = emit(opcode, dst, src0, src1);
+   } else if (brw->gen >= 6) {
       src0 = fix_math_operand(src0);
       src1 = fix_math_operand(src1);
 
@@ -1437,18 +1451,16 @@ void
 fs_visitor::assign_curb_setup()
 {
    if (dispatch_width == 8) {
-      c->prog_data.first_curbe_grf = c->nr_payload_regs;
+      prog_data->base.dispatch_grf_start_reg = payload.num_regs;
    } else {
-      c->prog_data.first_curbe_grf_16 = c->nr_payload_regs;
+      prog_data->dispatch_grf_start_reg_16 = payload.num_regs;
    }
 
-   c->prog_data.curb_read_length = ALIGN(stage_prog_data->nr_params, 8) / 8;
+   prog_data->curb_read_length = ALIGN(stage_prog_data->nr_params, 8) / 8;
 
    /* Map the offsets in the UNIFORM file to fixed HW regs. */
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      for (unsigned int i = 0; i < 3; i++) {
+   foreach_in_list(fs_inst, inst, &instructions) {
+      for (unsigned int i = 0; i < inst->sources; i++) {
         if (inst->src[i].file == UNIFORM) {
             int uniform_nr = inst->src[i].reg + inst->src[i].reg_offset;
             int constant_nr;
@@ -1463,7 +1475,7 @@ fs_visitor::assign_curb_setup()
                constant_nr = 0;
             }
 
-           struct brw_reg brw_reg = brw_vec1_grf(c->nr_payload_regs +
+           struct brw_reg brw_reg = brw_vec1_grf(payload.num_regs +
                                                  constant_nr / 8,
                                                  constant_nr % 8);
 
@@ -1480,7 +1492,7 @@ void
 fs_visitor::calculate_urb_setup()
 {
    for (unsigned int i = 0; i < VARYING_SLOT_MAX; i++) {
-      c->prog_data.urb_setup[i] = -1;
+      prog_data->urb_setup[i] = -1;
    }
 
    int urb_next = 0;
@@ -1500,7 +1512,7 @@ fs_visitor::calculate_urb_setup()
          for (unsigned int i = 0; i < VARYING_SLOT_MAX; i++) {
             if (fp->Base.InputsRead & BRW_FS_VARYING_INPUT_MASK &
                 BITFIELD64_BIT(i)) {
-               c->prog_data.urb_setup[i] = urb_next++;
+               prog_data->urb_setup[i] = urb_next++;
             }
          }
       } else {
@@ -1511,7 +1523,7 @@ fs_visitor::calculate_urb_setup()
           */
          struct brw_vue_map prev_stage_vue_map;
          brw_compute_vue_map(brw, &prev_stage_vue_map,
-                             c->key.input_slots_valid);
+                             key->input_slots_valid);
          int first_slot = 2 * BRW_SF_URB_ENTRY_READ_OFFSET;
          assert(prev_stage_vue_map.num_slots <= first_slot + 32);
          for (int slot = first_slot; slot < prev_stage_vue_map.num_slots;
@@ -1523,7 +1535,7 @@ fs_visitor::calculate_urb_setup()
             if (varying != BRW_VARYING_SLOT_COUNT &&
                 (fp->Base.InputsRead & BRW_FS_VARYING_INPUT_MASK &
                  BITFIELD64_BIT(varying))) {
-               c->prog_data.urb_setup[varying] = slot - first_slot;
+               prog_data->urb_setup[varying] = slot - first_slot;
             }
          }
          urb_next = prev_stage_vue_map.num_slots - first_slot;
@@ -1535,7 +1547,7 @@ fs_visitor::calculate_urb_setup()
          if (i == VARYING_SLOT_PSIZ)
             continue;
 
-        if (c->key.input_slots_valid & BITFIELD64_BIT(i)) {
+        if (key->input_slots_valid & BITFIELD64_BIT(i)) {
            /* The back color slot is skipped when the front color is
             * also written to.  In addition, some slots can be
             * written in the vertex shader and not read in the
@@ -1543,7 +1555,7 @@ fs_visitor::calculate_urb_setup()
             * incremented, mapped or not.
             */
            if (_mesa_varying_slot_in_fs((gl_varying_slot) i))
-              c->prog_data.urb_setup[i] = urb_next;
+              prog_data->urb_setup[i] = urb_next;
             urb_next++;
         }
       }
@@ -1555,23 +1567,21 @@ fs_visitor::calculate_urb_setup()
        * See compile_sf_prog() for more info.
        */
       if (fp->Base.InputsRead & BITFIELD64_BIT(VARYING_SLOT_PNTC))
-         c->prog_data.urb_setup[VARYING_SLOT_PNTC] = urb_next++;
+         prog_data->urb_setup[VARYING_SLOT_PNTC] = urb_next++;
    }
 
-   c->prog_data.num_varying_inputs = urb_next;
+   prog_data->num_varying_inputs = urb_next;
 }
 
 void
 fs_visitor::assign_urb_setup()
 {
-   int urb_start = c->nr_payload_regs + c->prog_data.curb_read_length;
+   int urb_start = payload.num_regs + prog_data->curb_read_length;
 
    /* Offset all the urb_setup[] index by the actual position of the
     * setup regs, now that the location of the constants has been chosen.
     */
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list(fs_inst, inst, &instructions) {
       if (inst->opcode == FS_OPCODE_LINTERP) {
         assert(inst->src[2].file == HW_REG);
         inst->src[2].fixed_hw_reg.nr += urb_start;
@@ -1585,7 +1595,7 @@ fs_visitor::assign_urb_setup()
 
    /* Each attribute is 4 setup channels, each of which is half a reg. */
    this->first_non_payload_grf =
-      urb_start + c->prog_data.num_varying_inputs * 2;
+      urb_start + prog_data->num_varying_inputs * 2;
 }
 
 /**
@@ -1632,9 +1642,7 @@ fs_visitor::split_virtual_grfs()
          false;
    }
 
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list(fs_inst, inst, &instructions) {
       /* If there's a SEND message that requires contiguous destination
        * registers, no splitting is allowed.
        */
@@ -1646,7 +1654,7 @@ fs_visitor::split_virtual_grfs()
        * the send is reading the whole thing.
        */
       if (inst->is_send_from_grf()) {
-         for (int i = 0; i < 3; i++) {
+         for (int i = 0; i < inst->sources; i++) {
             if (inst->src[i].file == GRF) {
                split_grf[inst->src[i].reg] = false;
             }
@@ -1669,9 +1677,7 @@ fs_visitor::split_virtual_grfs()
       }
    }
 
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list(fs_inst, inst, &instructions) {
       if (inst->dst.file == GRF &&
          split_grf[inst->dst.reg] &&
          inst->dst.reg_offset != 0) {
@@ -1679,7 +1685,7 @@ fs_visitor::split_virtual_grfs()
                          inst->dst.reg_offset - 1);
         inst->dst.reg_offset = 0;
       }
-      for (int i = 0; i < 3; i++) {
+      for (int i = 0; i < inst->sources; i++) {
         if (inst->src[i].file == GRF &&
             split_grf[inst->src[i].reg] &&
             inst->src[i].reg_offset != 0) {
@@ -1704,43 +1710,23 @@ fs_visitor::split_virtual_grfs()
 void
 fs_visitor::compact_virtual_grfs()
 {
+   if (unlikely(INTEL_DEBUG & DEBUG_OPTIMIZER))
+      return;
+
    /* Mark which virtual GRFs are used, and count how many. */
    int remap_table[this->virtual_grf_count];
    memset(remap_table, -1, sizeof(remap_table));
 
-   foreach_list(node, &this->instructions) {
-      const fs_inst *inst = (const fs_inst *) node;
-
+   foreach_in_list(const fs_inst, inst, &instructions) {
       if (inst->dst.file == GRF)
          remap_table[inst->dst.reg] = 0;
 
-      for (int i = 0; i < 3; i++) {
+      for (int i = 0; i < inst->sources; i++) {
          if (inst->src[i].file == GRF)
             remap_table[inst->src[i].reg] = 0;
       }
    }
 
-   /* In addition to registers used in instructions, fs_visitor keeps
-    * direct references to certain special values which must be patched:
-    */
-   fs_reg *special[] = {
-      &frag_depth, &pixel_x, &pixel_y, &pixel_w, &wpos_w, &dual_src_output,
-      &outputs[0], &outputs[1], &outputs[2], &outputs[3],
-      &outputs[4], &outputs[5], &outputs[6], &outputs[7],
-      &delta_x[0], &delta_x[1], &delta_x[2],
-      &delta_x[3], &delta_x[4], &delta_x[5],
-      &delta_y[0], &delta_y[1], &delta_y[2],
-      &delta_y[3], &delta_y[4], &delta_y[5],
-   };
-   STATIC_ASSERT(BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT == 6);
-   STATIC_ASSERT(BRW_MAX_DRAW_BUFFERS == 8);
-
-   /* Treat all special values as used, to be conservative */
-   for (unsigned i = 0; i < ARRAY_SIZE(special); i++) {
-      if (special[i]->file == GRF)
-        remap_table[special[i]->reg] = 0;
-   }
-
    /* Compact the GRF arrays. */
    int new_index = 0;
    for (int i = 0; i < this->virtual_grf_count; i++) {
@@ -1755,23 +1741,15 @@ fs_visitor::compact_virtual_grfs()
    this->virtual_grf_count = new_index;
 
    /* Patch all the instructions to use the newly renumbered registers */
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *) node;
-
+   foreach_in_list(fs_inst, inst, &instructions) {
       if (inst->dst.file == GRF)
          inst->dst.reg = remap_table[inst->dst.reg];
 
-      for (int i = 0; i < 3; i++) {
+      for (int i = 0; i < inst->sources; i++) {
          if (inst->src[i].file == GRF)
             inst->src[i].reg = remap_table[inst->src[i].reg];
       }
    }
-
-   /* Patch all the references to special values */
-   for (unsigned i = 0; i < ARRAY_SIZE(special); i++) {
-      if (special[i]->file == GRF && remap_table[special[i]->reg] != -1)
-        special[i]->reg = remap_table[special[i]->reg];
-   }
 }
 
 /*
@@ -1804,10 +1782,8 @@ fs_visitor::move_uniform_array_access_to_pull_constants()
     * Note that we don't move constant-indexed accesses to arrays.  No
     * testing has been done of the performance impact of this choice.
     */
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      for (int i = 0 ; i < 3; i++) {
+   foreach_in_list_safe(fs_inst, inst, &instructions) {
+      for (int i = 0 ; i < inst->sources; i++) {
          if (inst->src[i].file != UNIFORM || !inst->src[i].reladdr)
             continue;
 
@@ -1854,10 +1830,8 @@ fs_visitor::assign_constant_locations()
       is_live[i] = false;
    }
 
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *) node;
-
-      for (int i = 0; i < 3; i++) {
+   foreach_in_list(fs_inst, inst, &instructions) {
+      for (int i = 0; i < inst->sources; i++) {
          if (inst->src[i].file != UNIFORM)
             continue;
 
@@ -1871,6 +1845,9 @@ fs_visitor::assign_constant_locations()
     *
     * Just demote the end of the list.  We could probably do better
     * here, demoting things that are rarely used in the program first.
+    *
+    * If changing this value, note the limitation about total_regs in
+    * brw_curbe.c.
     */
    unsigned int max_push_components = 16 * 8;
    unsigned int num_push_constants = 0;
@@ -1925,10 +1902,8 @@ fs_visitor::assign_constant_locations()
 void
 fs_visitor::demote_pull_constants()
 {
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      for (int i = 0; i < 3; i++) {
+   foreach_in_list(fs_inst, inst, &instructions) {
+      for (int i = 0; i < inst->sources; i++) {
         if (inst->src[i].file != UNIFORM)
            continue;
 
@@ -1975,9 +1950,7 @@ fs_visitor::opt_algebraic()
 {
    bool progress = false;
 
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list(fs_inst, inst, &instructions) {
       switch (inst->opcode) {
       case BRW_OPCODE_MUL:
         if (inst->src[1].file != IMM)
@@ -2032,13 +2005,19 @@ fs_visitor::opt_algebraic()
          }
          break;
       case BRW_OPCODE_SEL:
-         if (inst->saturate && inst->src[1].file == IMM) {
+         if (inst->src[0].equals(inst->src[1])) {
+            inst->opcode = BRW_OPCODE_MOV;
+            inst->src[1] = reg_undef;
+            inst->predicate = BRW_PREDICATE_NONE;
+            inst->predicate_inverse = false;
+            progress = true;
+         } else if (inst->saturate && inst->src[1].file == IMM) {
             switch (inst->conditional_mod) {
             case BRW_CONDITIONAL_LE:
             case BRW_CONDITIONAL_L:
                switch (inst->src[1].type) {
                case BRW_REGISTER_TYPE_F:
-                  if (inst->src[1].imm.f >= 1.0f) {
+                  if (inst->src[1].fixed_hw_reg.dw1.f >= 1.0f) {
                      inst->opcode = BRW_OPCODE_MOV;
                      inst->src[1] = reg_undef;
                      progress = true;
@@ -2052,7 +2031,7 @@ fs_visitor::opt_algebraic()
             case BRW_CONDITIONAL_G:
                switch (inst->src[1].type) {
                case BRW_REGISTER_TYPE_F:
-                  if (inst->src[1].imm.f <= 0.0f) {
+                  if (inst->src[1].fixed_hw_reg.dw1.f <= 0.0f) {
                      inst->opcode = BRW_OPCODE_MOV;
                      inst->src[1] = reg_undef;
                      inst->conditional_mod = BRW_CONDITIONAL_NONE;
@@ -2075,399 +2054,6 @@ fs_visitor::opt_algebraic()
    return progress;
 }
 
-/**
- * Removes any instructions writing a VGRF where that VGRF is not used by any
- * later instruction.
- */
-bool
-fs_visitor::dead_code_eliminate()
-{
-   bool progress = false;
-   int pc = 0;
-
-   calculate_live_intervals();
-
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      if (inst->dst.file == GRF && !inst->has_side_effects()) {
-         bool dead = true;
-
-         for (int i = 0; i < inst->regs_written; i++) {
-            int var = live_intervals->var_from_vgrf[inst->dst.reg];
-            assert(live_intervals->end[var + inst->dst.reg_offset + i] >= pc);
-            if (live_intervals->end[var + inst->dst.reg_offset + i] != pc) {
-               dead = false;
-               break;
-            }
-         }
-
-         if (dead) {
-            /* Don't dead code eliminate instructions that write to the
-             * accumulator as a side-effect. Instead just set the destination
-             * to the null register to free it.
-             */
-            switch (inst->opcode) {
-            case BRW_OPCODE_ADDC:
-            case BRW_OPCODE_SUBB:
-            case BRW_OPCODE_MACH:
-               inst->dst = fs_reg(retype(brw_null_reg(), inst->dst.type));
-               break;
-            default:
-               inst->remove();
-               progress = true;
-               break;
-            }
-         }
-      }
-
-      pc++;
-   }
-
-   if (progress)
-      invalidate_live_intervals();
-
-   return progress;
-}
-
-struct dead_code_hash_key
-{
-   int vgrf;
-   int reg_offset;
-};
-
-static bool
-dead_code_hash_compare(const void *a, const void *b)
-{
-   return memcmp(a, b, sizeof(struct dead_code_hash_key)) == 0;
-}
-
-static void
-clear_dead_code_hash(struct hash_table *ht)
-{
-   struct hash_entry *entry;
-
-   hash_table_foreach(ht, entry) {
-      _mesa_hash_table_remove(ht, entry);
-   }
-}
-
-static void
-insert_dead_code_hash(struct hash_table *ht,
-                      int vgrf, int reg_offset, fs_inst *inst)
-{
-   /* We don't bother freeing keys, because they'll be GCed with the ht. */
-   struct dead_code_hash_key *key = ralloc(ht, struct dead_code_hash_key);
-
-   key->vgrf = vgrf;
-   key->reg_offset = reg_offset;
-
-   _mesa_hash_table_insert(ht, _mesa_hash_data(key, sizeof(*key)), key, inst);
-}
-
-static struct hash_entry *
-get_dead_code_hash_entry(struct hash_table *ht, int vgrf, int reg_offset)
-{
-   struct dead_code_hash_key key;
-
-   key.vgrf = vgrf;
-   key.reg_offset = reg_offset;
-
-   return _mesa_hash_table_search(ht, _mesa_hash_data(&key, sizeof(key)), &key);
-}
-
-static void
-remove_dead_code_hash(struct hash_table *ht,
-                      int vgrf, int reg_offset)
-{
-   struct hash_entry *entry = get_dead_code_hash_entry(ht, vgrf, reg_offset);
-   if (!entry)
-      return;
-
-   _mesa_hash_table_remove(ht, entry);
-}
-
-/**
- * Walks basic blocks, removing any regs that are written but not read before
- * being redefined.
- *
- * The dead_code_eliminate() function implements a global dead code
- * elimination, but it only handles the removing the last write to a register
- * if it's never read.  This one can handle intermediate writes, but only
- * within a basic block.
- */
-bool
-fs_visitor::dead_code_eliminate_local()
-{
-   struct hash_table *ht;
-   bool progress = false;
-
-   ht = _mesa_hash_table_create(mem_ctx, dead_code_hash_compare);
-
-   if (ht == NULL) {
-      return false;
-   }
-
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      /* At a basic block, empty the HT since we don't understand dataflow
-       * here.
-       */
-      if (inst->is_control_flow()) {
-         clear_dead_code_hash(ht);
-         continue;
-      }
-
-      /* Clear the HT of any instructions that got read. */
-      for (int i = 0; i < 3; i++) {
-         fs_reg src = inst->src[i];
-         if (src.file != GRF)
-            continue;
-
-         int read = 1;
-         if (inst->is_send_from_grf())
-            read = virtual_grf_sizes[src.reg] - src.reg_offset;
-
-         for (int reg_offset = src.reg_offset;
-              reg_offset < src.reg_offset + read;
-              reg_offset++) {
-            remove_dead_code_hash(ht, src.reg, reg_offset);
-         }
-      }
-
-      /* Add any update of a GRF to the HT, removing a previous write if it
-       * wasn't read.
-       */
-      if (inst->dst.file == GRF) {
-         if (inst->regs_written > 1) {
-            /* We don't know how to trim channels from an instruction's
-             * writes, so we can't incrementally remove unread channels from
-             * it.  Just remove whatever it overwrites from the table
-             */
-            for (int i = 0; i < inst->regs_written; i++) {
-               remove_dead_code_hash(ht,
-                                     inst->dst.reg,
-                                     inst->dst.reg_offset + i);
-            }
-         } else {
-            struct hash_entry *entry =
-               get_dead_code_hash_entry(ht, inst->dst.reg,
-                                        inst->dst.reg_offset);
-
-            if (entry) {
-               if (inst->is_partial_write()) {
-                  /* For a partial write, we can't remove any previous dead code
-                   * candidate, since we're just modifying their result.
-                   */
-               } else {
-                  /* We're completely updating a channel, and there was a
-                   * previous write to the channel that wasn't read.  Kill it!
-                   */
-                  fs_inst *inst = (fs_inst *)entry->data;
-                  inst->remove();
-                  progress = true;
-               }
-
-               _mesa_hash_table_remove(ht, entry);
-            }
-
-            if (!inst->has_side_effects())
-               insert_dead_code_hash(ht, inst->dst.reg, inst->dst.reg_offset,
-                                     inst);
-         }
-      }
-   }
-
-   _mesa_hash_table_destroy(ht, NULL);
-
-   if (progress)
-      invalidate_live_intervals();
-
-   return progress;
-}
-
-/**
- * Implements register coalescing: Checks if the two registers involved in a
- * raw move don't interfere, in which case they can both be stored in the same
- * place and the MOV removed.
- *
- * To do this, all uses of the source of the MOV in the shader are replaced
- * with the destination of the MOV. For example:
- *
- * add vgrf3:F, vgrf1:F, vgrf2:F
- * mov vgrf4:F, vgrf3:F
- * mul vgrf5:F, vgrf5:F, vgrf4:F
- *
- * becomes
- *
- * add vgrf4:F, vgrf1:F, vgrf2:F
- * mul vgrf5:F, vgrf5:F, vgrf4:F
- */
-bool
-fs_visitor::register_coalesce()
-{
-   bool progress = false;
-
-   calculate_live_intervals();
-
-   int src_size = 0;
-   int channels_remaining = 0;
-   int reg_from = -1, reg_to = -1;
-   int reg_to_offset[MAX_SAMPLER_MESSAGE_SIZE];
-   fs_inst *mov[MAX_SAMPLER_MESSAGE_SIZE];
-
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      if (inst->opcode != BRW_OPCODE_MOV ||
-         inst->is_partial_write() ||
-         inst->saturate ||
-         inst->src[0].file != GRF ||
-         inst->src[0].negate ||
-         inst->src[0].abs ||
-         !inst->src[0].is_contiguous() ||
-         inst->dst.file != GRF ||
-         inst->dst.type != inst->src[0].type) {
-        continue;
-      }
-
-      if (virtual_grf_sizes[inst->src[0].reg] >
-          virtual_grf_sizes[inst->dst.reg])
-         continue;
-
-      int var_from = live_intervals->var_from_reg(&inst->src[0]);
-      int var_to = live_intervals->var_from_reg(&inst->dst);
-
-      if (live_intervals->vars_interfere(var_from, var_to) &&
-          !inst->dst.equals(inst->src[0])) {
-
-         /* We know that the live ranges of A (var_from) and B (var_to)
-          * interfere because of the ->vars_interfere() call above. If the end
-          * of B's live range is after the end of A's range, then we know two
-          * things:
-          *  - the start of B's live range must be in A's live range (since we
-          *    already know the two ranges interfere, this is the only remaining
-          *    possibility)
-          *  - the interference isn't of the form we're looking for (where B is
-          *    entirely inside A)
-          */
-         if (live_intervals->end[var_to] > live_intervals->end[var_from])
-            continue;
-
-         bool overwritten = false;
-         int scan_ip = -1;
-
-         foreach_list(n, &this->instructions) {
-            fs_inst *scan_inst = (fs_inst *)n;
-            scan_ip++;
-
-            if (scan_inst->is_control_flow()) {
-               overwritten = true;
-               break;
-            }
-
-            if (scan_ip <= live_intervals->start[var_to])
-               continue;
-
-            if (scan_ip > live_intervals->end[var_to])
-               break;
-
-            if (scan_inst->dst.equals(inst->dst) ||
-                scan_inst->dst.equals(inst->src[0])) {
-               overwritten = true;
-               break;
-            }
-         }
-
-         if (overwritten)
-            continue;
-      }
-
-      if (reg_from != inst->src[0].reg) {
-         reg_from = inst->src[0].reg;
-
-         src_size = virtual_grf_sizes[inst->src[0].reg];
-         assert(src_size <= MAX_SAMPLER_MESSAGE_SIZE);
-
-         channels_remaining = src_size;
-         memset(mov, 0, sizeof(mov));
-
-         reg_to = inst->dst.reg;
-      }
-
-      if (reg_to != inst->dst.reg)
-         continue;
-
-      const int offset = inst->src[0].reg_offset;
-      reg_to_offset[offset] = inst->dst.reg_offset;
-      mov[offset] = inst;
-      channels_remaining--;
-
-      if (channels_remaining)
-         continue;
-
-      bool removed = false;
-      for (int i = 0; i < src_size; i++) {
-         if (mov[i]) {
-            removed = true;
-
-            mov[i]->opcode = BRW_OPCODE_NOP;
-            mov[i]->conditional_mod = BRW_CONDITIONAL_NONE;
-            mov[i]->dst = reg_undef;
-            mov[i]->src[0] = reg_undef;
-            mov[i]->src[1] = reg_undef;
-            mov[i]->src[2] = reg_undef;
-         }
-      }
-
-      foreach_list(node, &this->instructions) {
-         fs_inst *scan_inst = (fs_inst *)node;
-
-         for (int i = 0; i < src_size; i++) {
-            if (mov[i]) {
-               if (scan_inst->dst.file == GRF &&
-                   scan_inst->dst.reg == reg_from &&
-                   scan_inst->dst.reg_offset == i) {
-                  scan_inst->dst.reg = reg_to;
-                  scan_inst->dst.reg_offset = reg_to_offset[i];
-               }
-               for (int j = 0; j < 3; j++) {
-                  if (scan_inst->src[j].file == GRF &&
-                      scan_inst->src[j].reg == reg_from &&
-                      scan_inst->src[j].reg_offset == i) {
-                     scan_inst->src[j].reg = reg_to;
-                     scan_inst->src[j].reg_offset = reg_to_offset[i];
-                  }
-               }
-            }
-         }
-      }
-
-      if (removed) {
-         live_intervals->start[var_to] = MIN2(live_intervals->start[var_to],
-                                              live_intervals->start[var_from]);
-         live_intervals->end[var_to] = MAX2(live_intervals->end[var_to],
-                                            live_intervals->end[var_from]);
-         reg_from = -1;
-      }
-   }
-
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
-      if (inst->opcode == BRW_OPCODE_NOP) {
-         inst->remove();
-         progress = true;
-      }
-   }
-
-   if (progress)
-      invalidate_live_intervals();
-
-   return progress;
-}
-
 bool
 fs_visitor::compute_to_mrf()
 {
@@ -2476,9 +2062,7 @@ fs_visitor::compute_to_mrf()
 
    calculate_live_intervals();
 
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list_safe(fs_inst, inst, &instructions) {
       int ip = next_ip;
       next_ip++;
 
@@ -2516,7 +2100,7 @@ fs_visitor::compute_to_mrf()
        */
       fs_inst *scan_inst;
       for (scan_inst = (fs_inst *)inst->prev;
-          scan_inst->prev != NULL;
+           !scan_inst->is_head_sentinel();
           scan_inst = (fs_inst *)scan_inst->prev) {
         if (scan_inst->dst.file == GRF &&
             scan_inst->dst.reg == inst->src[0].reg) {
@@ -2573,7 +2157,7 @@ fs_visitor::compute_to_mrf()
          * MRF's source GRF that we wanted to rewrite, that stops us.
          */
         bool interfered = false;
-        for (int i = 0; i < 3; i++) {
+        for (int i = 0; i < scan_inst->sources; i++) {
            if (scan_inst->src[i].file == GRF &&
                scan_inst->src[i].reg == inst->src[0].reg &&
                scan_inst->src[i].reg_offset == inst->src[0].reg_offset) {
@@ -2648,9 +2232,7 @@ fs_visitor::remove_duplicate_mrf_writes()
 
    memset(last_mrf_move, 0, sizeof(last_mrf_move));
 
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list_safe(fs_inst, inst, &instructions) {
       if (inst->is_control_flow()) {
         memset(last_mrf_move, 0, sizeof(last_mrf_move));
       }
@@ -2712,7 +2294,7 @@ clear_deps_for_inst_src(fs_inst *inst, int dispatch_width, bool *deps,
                        !inst->force_sechalf);
 
    /* Clear the flag for registers that actually got read (as expected). */
-   for (int i = 0; i < 3; i++) {
+   for (int i = 0; i < inst->sources; i++) {
       int grf;
       if (inst->src[i].file == GRF) {
          grf = inst->src[i].reg;
@@ -2769,7 +2351,7 @@ fs_visitor::insert_gen4_pre_send_dependency_workarounds(fs_inst *inst)
     * program.
     */
    for (fs_inst *scan_inst = (fs_inst *)inst->prev;
-        scan_inst != NULL;
+        !scan_inst->is_head_sentinel();
         scan_inst = (fs_inst *)scan_inst->prev) {
 
       /* If we hit control flow, assume that there *are* outstanding
@@ -2896,18 +2478,22 @@ fs_visitor::insert_gen4_send_dependency_workarounds()
    if (brw->gen != 4 || brw->is_g4x)
       return;
 
+   bool progress = false;
+
    /* Note that we're done with register allocation, so GRF fs_regs always
     * have a .reg_offset of 0.
     */
 
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list_safe(fs_inst, inst, &instructions) {
       if (inst->mlen != 0 && inst->dst.file == GRF) {
          insert_gen4_pre_send_dependency_workarounds(inst);
          insert_gen4_post_send_dependency_workarounds(inst);
+         progress = true;
       }
    }
+
+   if (progress)
+      invalidate_live_intervals();
 }
 
 /**
@@ -2929,9 +2515,7 @@ fs_visitor::insert_gen4_send_dependency_workarounds()
 void
 fs_visitor::lower_uniform_pull_constant_loads()
 {
-   foreach_list(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list(fs_inst, inst, &instructions) {
       if (inst->opcode != FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD)
          continue;
 
@@ -2942,7 +2526,7 @@ fs_visitor::lower_uniform_pull_constant_loads()
          fs_reg const_offset_reg = inst->src[1];
          assert(const_offset_reg.file == IMM &&
                 const_offset_reg.type == BRW_REGISTER_TYPE_UD);
-         const_offset_reg.imm.u /= 4;
+         const_offset_reg.fixed_hw_reg.dw1.ud /= 4;
          fs_reg payload = fs_reg(this, glsl_type::uint_type);
 
          /* This is actually going to be a MOV, but since only the first dword
@@ -2978,200 +2562,252 @@ fs_visitor::lower_uniform_pull_constant_loads()
    }
 }
 
+bool
+fs_visitor::lower_load_payload()
+{
+   bool progress = false;
+
+   foreach_in_list_safe(fs_inst, inst, &instructions) {
+      if (inst->opcode == SHADER_OPCODE_LOAD_PAYLOAD) {
+         fs_reg dst = inst->dst;
+
+         /* src[0] represents the (optional) message header. */
+         if (inst->src[0].file != BAD_FILE) {
+            inst->insert_before(MOV(dst, inst->src[0]));
+         }
+         dst.reg_offset++;
+
+         for (int i = 1; i < inst->sources; i++) {
+            inst->insert_before(MOV(dst, inst->src[i]));
+            dst.reg_offset++;
+         }
+
+         inst->remove();
+         progress = true;
+      }
+   }
+
+   if (progress)
+      invalidate_live_intervals();
+
+   return progress;
+}
+
 void
 fs_visitor::dump_instructions()
+{
+   dump_instructions(NULL);
+}
+
+void
+fs_visitor::dump_instructions(const char *name)
 {
    calculate_register_pressure();
+   FILE *file = stderr;
+   if (name && geteuid() != 0) {
+      file = fopen(name, "w");
+      if (!file)
+         file = stderr;
+   }
 
    int ip = 0, max_pressure = 0;
-   foreach_list(node, &this->instructions) {
-      backend_instruction *inst = (backend_instruction *)node;
+   foreach_in_list(backend_instruction, inst, &instructions) {
       max_pressure = MAX2(max_pressure, regs_live_at_ip[ip]);
-      fprintf(stderr, "{%3d} %4d: ", regs_live_at_ip[ip], ip);
-      dump_instruction(inst);
+      fprintf(file, "{%3d} %4d: ", regs_live_at_ip[ip], ip);
+      dump_instruction(inst, file);
       ++ip;
    }
-   fprintf(stderr, "Maximum %3d registers live at once.\n", max_pressure);
+   fprintf(file, "Maximum %3d registers live at once.\n", max_pressure);
+
+   if (file != stderr) {
+      fclose(file);
+   }
 }
 
 void
 fs_visitor::dump_instruction(backend_instruction *be_inst)
+{
+   dump_instruction(be_inst, stderr);
+}
+
+void
+fs_visitor::dump_instruction(backend_instruction *be_inst, FILE *file)
 {
    fs_inst *inst = (fs_inst *)be_inst;
 
    if (inst->predicate) {
-      fprintf(stderr, "(%cf0.%d) ",
+      fprintf(file, "(%cf0.%d) ",
              inst->predicate_inverse ? '-' : '+',
              inst->flag_subreg);
    }
 
-   fprintf(stderr, "%s", brw_instruction_name(inst->opcode));
+   fprintf(file, "%s", brw_instruction_name(inst->opcode));
    if (inst->saturate)
-      fprintf(stderr, ".sat");
+      fprintf(file, ".sat");
    if (inst->conditional_mod) {
-      fprintf(stderr, "%s", conditional_modifier[inst->conditional_mod]);
+      fprintf(file, "%s", conditional_modifier[inst->conditional_mod]);
       if (!inst->predicate &&
           (brw->gen < 5 || (inst->opcode != BRW_OPCODE_SEL &&
                               inst->opcode != BRW_OPCODE_IF &&
                               inst->opcode != BRW_OPCODE_WHILE))) {
-         fprintf(stderr, ".f0.%d", inst->flag_subreg);
+         fprintf(file, ".f0.%d", inst->flag_subreg);
       }
    }
-   fprintf(stderr, " ");
+   fprintf(file, " ");
 
 
    switch (inst->dst.file) {
    case GRF:
-      fprintf(stderr, "vgrf%d", inst->dst.reg);
+      fprintf(file, "vgrf%d", inst->dst.reg);
       if (virtual_grf_sizes[inst->dst.reg] != 1 ||
           inst->dst.subreg_offset)
-         fprintf(stderr, "+%d.%d",
+         fprintf(file, "+%d.%d",
                  inst->dst.reg_offset, inst->dst.subreg_offset);
       break;
    case MRF:
-      fprintf(stderr, "m%d", inst->dst.reg);
+      fprintf(file, "m%d", inst->dst.reg);
       break;
    case BAD_FILE:
-      fprintf(stderr, "(null)");
+      fprintf(file, "(null)");
       break;
    case UNIFORM:
-      fprintf(stderr, "***u%d***", inst->dst.reg);
+      fprintf(file, "***u%d***", inst->dst.reg + inst->dst.reg_offset);
       break;
    case HW_REG:
       if (inst->dst.fixed_hw_reg.file == BRW_ARCHITECTURE_REGISTER_FILE) {
          switch (inst->dst.fixed_hw_reg.nr) {
          case BRW_ARF_NULL:
-            fprintf(stderr, "null");
+            fprintf(file, "null");
             break;
          case BRW_ARF_ADDRESS:
-            fprintf(stderr, "a0.%d", inst->dst.fixed_hw_reg.subnr);
+            fprintf(file, "a0.%d", inst->dst.fixed_hw_reg.subnr);
             break;
          case BRW_ARF_ACCUMULATOR:
-            fprintf(stderr, "acc%d", inst->dst.fixed_hw_reg.subnr);
+            fprintf(file, "acc%d", inst->dst.fixed_hw_reg.subnr);
             break;
          case BRW_ARF_FLAG:
-            fprintf(stderr, "f%d.%d", inst->dst.fixed_hw_reg.nr & 0xf,
+            fprintf(file, "f%d.%d", inst->dst.fixed_hw_reg.nr & 0xf,
                              inst->dst.fixed_hw_reg.subnr);
             break;
          default:
-            fprintf(stderr, "arf%d.%d", inst->dst.fixed_hw_reg.nr & 0xf,
+            fprintf(file, "arf%d.%d", inst->dst.fixed_hw_reg.nr & 0xf,
                                inst->dst.fixed_hw_reg.subnr);
             break;
          }
       } else {
-         fprintf(stderr, "hw_reg%d", inst->dst.fixed_hw_reg.nr);
+         fprintf(file, "hw_reg%d", inst->dst.fixed_hw_reg.nr);
       }
       if (inst->dst.fixed_hw_reg.subnr)
-         fprintf(stderr, "+%d", inst->dst.fixed_hw_reg.subnr);
+         fprintf(file, "+%d", inst->dst.fixed_hw_reg.subnr);
       break;
    default:
-      fprintf(stderr, "???");
+      fprintf(file, "???");
       break;
    }
-   fprintf(stderr, ":%s, ", brw_reg_type_letters(inst->dst.type));
+   fprintf(file, ":%s, ", brw_reg_type_letters(inst->dst.type));
 
-   for (int i = 0; i < 3 && inst->src[i].file != BAD_FILE; i++) {
+   for (int i = 0; i < inst->sources && inst->src[i].file != BAD_FILE; i++) {
       if (inst->src[i].negate)
-         fprintf(stderr, "-");
+         fprintf(file, "-");
       if (inst->src[i].abs)
-         fprintf(stderr, "|");
+         fprintf(file, "|");
       switch (inst->src[i].file) {
       case GRF:
-         fprintf(stderr, "vgrf%d", inst->src[i].reg);
+         fprintf(file, "vgrf%d", inst->src[i].reg);
          if (virtual_grf_sizes[inst->src[i].reg] != 1 ||
              inst->src[i].subreg_offset)
-            fprintf(stderr, "+%d.%d", inst->src[i].reg_offset,
+            fprintf(file, "+%d.%d", inst->src[i].reg_offset,
                     inst->src[i].subreg_offset);
          break;
       case MRF:
-         fprintf(stderr, "***m%d***", inst->src[i].reg);
+         fprintf(file, "***m%d***", inst->src[i].reg);
          break;
       case UNIFORM:
-         fprintf(stderr, "u%d", inst->src[i].reg);
+         fprintf(file, "u%d", inst->src[i].reg + inst->src[i].reg_offset);
          if (inst->src[i].reladdr) {
-            fprintf(stderr, "+reladdr");
+            fprintf(file, "+reladdr");
          } else if (virtual_grf_sizes[inst->src[i].reg] != 1 ||
              inst->src[i].subreg_offset) {
-            fprintf(stderr, "+%d.%d", inst->src[i].reg_offset,
+            fprintf(file, "+%d.%d", inst->src[i].reg_offset,
                     inst->src[i].subreg_offset);
          }
          break;
       case BAD_FILE:
-         fprintf(stderr, "(null)");
+         fprintf(file, "(null)");
          break;
       case IMM:
          switch (inst->src[i].type) {
          case BRW_REGISTER_TYPE_F:
-            fprintf(stderr, "%ff", inst->src[i].imm.f);
+            fprintf(file, "%ff", inst->src[i].fixed_hw_reg.dw1.f);
             break;
          case BRW_REGISTER_TYPE_D:
-            fprintf(stderr, "%dd", inst->src[i].imm.i);
+            fprintf(file, "%dd", inst->src[i].fixed_hw_reg.dw1.d);
             break;
          case BRW_REGISTER_TYPE_UD:
-            fprintf(stderr, "%uu", inst->src[i].imm.u);
+            fprintf(file, "%uu", inst->src[i].fixed_hw_reg.dw1.ud);
             break;
          default:
-            fprintf(stderr, "???");
+            fprintf(file, "???");
             break;
          }
          break;
       case HW_REG:
          if (inst->src[i].fixed_hw_reg.negate)
-            fprintf(stderr, "-");
+            fprintf(file, "-");
          if (inst->src[i].fixed_hw_reg.abs)
-            fprintf(stderr, "|");
+            fprintf(file, "|");
          if (inst->src[i].fixed_hw_reg.file == BRW_ARCHITECTURE_REGISTER_FILE) {
             switch (inst->src[i].fixed_hw_reg.nr) {
             case BRW_ARF_NULL:
-               fprintf(stderr, "null");
+               fprintf(file, "null");
                break;
             case BRW_ARF_ADDRESS:
-               fprintf(stderr, "a0.%d", inst->src[i].fixed_hw_reg.subnr);
+               fprintf(file, "a0.%d", inst->src[i].fixed_hw_reg.subnr);
                break;
             case BRW_ARF_ACCUMULATOR:
-               fprintf(stderr, "acc%d", inst->src[i].fixed_hw_reg.subnr);
+               fprintf(file, "acc%d", inst->src[i].fixed_hw_reg.subnr);
                break;
             case BRW_ARF_FLAG:
-               fprintf(stderr, "f%d.%d", inst->src[i].fixed_hw_reg.nr & 0xf,
+               fprintf(file, "f%d.%d", inst->src[i].fixed_hw_reg.nr & 0xf,
                                 inst->src[i].fixed_hw_reg.subnr);
                break;
             default:
-               fprintf(stderr, "arf%d.%d", inst->src[i].fixed_hw_reg.nr & 0xf,
+               fprintf(file, "arf%d.%d", inst->src[i].fixed_hw_reg.nr & 0xf,
                                   inst->src[i].fixed_hw_reg.subnr);
                break;
             }
          } else {
-            fprintf(stderr, "hw_reg%d", inst->src[i].fixed_hw_reg.nr);
+            fprintf(file, "hw_reg%d", inst->src[i].fixed_hw_reg.nr);
          }
          if (inst->src[i].fixed_hw_reg.subnr)
-            fprintf(stderr, "+%d", inst->src[i].fixed_hw_reg.subnr);
+            fprintf(file, "+%d", inst->src[i].fixed_hw_reg.subnr);
          if (inst->src[i].fixed_hw_reg.abs)
-            fprintf(stderr, "|");
+            fprintf(file, "|");
          break;
       default:
-         fprintf(stderr, "???");
+         fprintf(file, "???");
          break;
       }
       if (inst->src[i].abs)
-         fprintf(stderr, "|");
+         fprintf(file, "|");
 
       if (inst->src[i].file != IMM) {
-         fprintf(stderr, ":%s", brw_reg_type_letters(inst->src[i].type));
+         fprintf(file, ":%s", brw_reg_type_letters(inst->src[i].type));
       }
 
-      if (i < 2 && inst->src[i + 1].file != BAD_FILE)
-         fprintf(stderr, ", ");
+      if (i < inst->sources - 1 && inst->src[i + 1].file != BAD_FILE)
+         fprintf(file, ", ");
    }
 
-   fprintf(stderr, " ");
+   fprintf(file, " ");
 
    if (inst->force_uncompressed)
-      fprintf(stderr, "1sthalf ");
+      fprintf(file, "1sthalf ");
 
    if (inst->force_sechalf)
-      fprintf(stderr, "2ndhalf ");
+      fprintf(file, "2ndhalf ");
 
-   fprintf(stderr, "\n");
+   fprintf(file, "\n");
 }
 
 /**
@@ -3207,12 +2843,12 @@ fs_visitor::setup_payload_gen6()
 {
    bool uses_depth =
       (fp->Base.InputsRead & (1 << VARYING_SLOT_POS)) != 0;
-   unsigned barycentric_interp_modes = c->prog_data.barycentric_interp_modes;
+   unsigned barycentric_interp_modes = prog_data->barycentric_interp_modes;
 
    assert(brw->gen >= 6);
 
    /* R0-1: masks, pixel X/Y coordinates. */
-   c->nr_payload_regs = 2;
+   payload.num_regs = 2;
    /* R2: only for 32-pixel dispatch.*/
 
    /* R3-26: barycentric interpolation coordinates.  These appear in the
@@ -3224,48 +2860,48 @@ fs_visitor::setup_payload_gen6()
     */
    for (int i = 0; i < BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT; ++i) {
       if (barycentric_interp_modes & (1 << i)) {
-         c->barycentric_coord_reg[i] = c->nr_payload_regs;
-         c->nr_payload_regs += 2;
+         payload.barycentric_coord_reg[i] = payload.num_regs;
+         payload.num_regs += 2;
          if (dispatch_width == 16) {
-            c->nr_payload_regs += 2;
+            payload.num_regs += 2;
          }
       }
    }
 
    /* R27: interpolated depth if uses source depth */
    if (uses_depth) {
-      c->source_depth_reg = c->nr_payload_regs;
-      c->nr_payload_regs++;
+      payload.source_depth_reg = payload.num_regs;
+      payload.num_regs++;
       if (dispatch_width == 16) {
          /* R28: interpolated depth if not SIMD8. */
-         c->nr_payload_regs++;
+         payload.num_regs++;
       }
    }
    /* R29: interpolated W set if GEN6_WM_USES_SOURCE_W. */
    if (uses_depth) {
-      c->source_w_reg = c->nr_payload_regs;
-      c->nr_payload_regs++;
+      payload.source_w_reg = payload.num_regs;
+      payload.num_regs++;
       if (dispatch_width == 16) {
          /* R30: interpolated W if not SIMD8. */
-         c->nr_payload_regs++;
+         payload.num_regs++;
       }
    }
 
-   c->prog_data.uses_pos_offset = c->key.compute_pos_offset;
+   prog_data->uses_pos_offset = key->compute_pos_offset;
    /* R31: MSAA position offsets. */
-   if (c->prog_data.uses_pos_offset) {
-      c->sample_pos_reg = c->nr_payload_regs;
-      c->nr_payload_regs++;
+   if (prog_data->uses_pos_offset) {
+      payload.sample_pos_reg = payload.num_regs;
+      payload.num_regs++;
    }
 
    /* R32: MSAA input coverage mask */
    if (fp->Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_MASK_IN) {
       assert(brw->gen >= 7);
-      c->sample_mask_reg = c->nr_payload_regs;
-      c->nr_payload_regs++;
+      payload.sample_mask_in_reg = payload.num_regs;
+      payload.num_regs++;
       if (dispatch_width == 16) {
          /* R33: input coverage mask if not SIMD8. */
-         c->nr_payload_regs++;
+         payload.num_regs++;
       }
    }
 
@@ -3273,7 +2909,7 @@ fs_visitor::setup_payload_gen6()
    /* R58-59: interp W for 32-pixel. */
 
    if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
-      c->source_depth_to_render_target = true;
+      source_depth_to_render_target = true;
    }
 }
 
@@ -3285,8 +2921,8 @@ fs_visitor::assign_binding_table_offsets()
    /* If there are no color regions, we still perform an FB write to a null
     * renderbuffer, which we place at surface index 0.
     */
-   c->prog_data.binding_table.render_target_start = next_binding_table_offset;
-   next_binding_table_offset += MAX2(c->key.nr_color_regions, 1);
+   prog_data->binding_table.render_target_start = next_binding_table_offset;
+   next_binding_table_offset += MAX2(key->nr_color_regions, 1);
 
    assign_common_binding_table_offsets(next_binding_table_offset);
 }
@@ -3294,12 +2930,10 @@ fs_visitor::assign_binding_table_offsets()
 void
 fs_visitor::calculate_register_pressure()
 {
+   invalidate_live_intervals();
    calculate_live_intervals();
 
-   int num_instructions = 0;
-   foreach_list(node, &this->instructions) {
-      ++num_instructions;
-   }
+   unsigned num_instructions = instructions.length();
 
    regs_live_at_ip = rzalloc_array(mem_ctx, int, num_instructions);
 
@@ -3324,9 +2958,7 @@ fs_visitor::opt_drop_redundant_mov_to_flags()
 {
    bool flag_mov_found[2] = {false};
 
-   foreach_list_safe(node, &this->instructions) {
-      fs_inst *inst = (fs_inst *)node;
-
+   foreach_in_list_safe(fs_inst, inst, &instructions) {
       if (inst->is_control_flow()) {
          memset(flag_mov_found, 0, sizeof(flag_mov_found));
       } else if (inst->opcode == FS_OPCODE_MOV_DISPATCH_TO_FLAGS) {
@@ -3370,7 +3002,7 @@ fs_visitor::run()
       /* We handle discards by keeping track of the still-live pixels in f0.1.
        * Initialize it with the dispatched pixels.
        */
-      if (fp->UsesKill || c->key.alpha_test_func) {
+      if (fp->UsesKill || key->alpha_test_func) {
          fs_inst *discard_init = emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS);
          discard_init->flag_subreg = 1;
       }
@@ -3379,8 +3011,7 @@ fs_visitor::run()
        * functions called "main").
        */
       if (shader) {
-         foreach_list(node, &*shader->base.ir) {
-            ir_instruction *ir = (ir_instruction *)node;
+         foreach_in_list(ir_instruction, ir, shader->base.ir) {
             base_ir = ir;
             this->result = reg_undef;
             ir->accept(this);
@@ -3394,7 +3025,7 @@ fs_visitor::run()
 
       emit(FS_OPCODE_PLACEHOLDER_HALT);
 
-      if (c->key.alpha_test_func)
+      if (key->alpha_test_func)
          emit_alpha_test();
 
       emit_fb_writes();
@@ -3407,27 +3038,57 @@ fs_visitor::run()
 
       opt_drop_redundant_mov_to_flags();
 
+#define OPT(pass, args...) do {                                            \
+      pass_num++;                                                          \
+      bool this_progress = pass(args);                                     \
+                                                                           \
+      if (unlikely(INTEL_DEBUG & DEBUG_OPTIMIZER) && this_progress) {      \
+         char filename[64];                                                \
+         snprintf(filename, 64, "fs%d-%04d-%02d-%02d-" #pass,              \
+                  dispatch_width, shader_prog->Name, iteration, pass_num); \
+                                                                           \
+         backend_visitor::dump_instructions(filename);                     \
+      }                                                                    \
+                                                                           \
+      progress = progress || this_progress;                                \
+   } while (false)
+
+      if (unlikely(INTEL_DEBUG & DEBUG_OPTIMIZER)) {
+         char filename[64];
+         snprintf(filename, 64, "fs%d-%04d-00-start",
+                  dispatch_width, shader_prog->Name);
+
+         backend_visitor::dump_instructions(filename);
+      }
+
       bool progress;
+      int iteration = 0;
       do {
         progress = false;
+         iteration++;
+         int pass_num = 0;
 
          compact_virtual_grfs();
 
-        progress = remove_duplicate_mrf_writes() || progress;
-
-        progress = opt_algebraic() || progress;
-        progress = opt_cse() || progress;
-        progress = opt_copy_propagate() || progress;
-         progress = opt_peephole_predicated_break() || progress;
-        progress = dead_code_eliminate() || progress;
-        progress = dead_code_eliminate_local() || progress;
-         progress = opt_peephole_sel() || progress;
-         progress = dead_control_flow_eliminate(this) || progress;
-         progress = opt_saturate_propagation() || progress;
-         progress = register_coalesce() || progress;
-        progress = compute_to_mrf() || progress;
+         OPT(remove_duplicate_mrf_writes);
+
+         OPT(opt_algebraic);
+         OPT(opt_cse);
+         OPT(opt_copy_propagate);
+         OPT(opt_peephole_predicated_break);
+         OPT(dead_code_eliminate);
+         OPT(opt_peephole_sel);
+         OPT(dead_control_flow_eliminate, this);
+         OPT(opt_saturate_propagation);
+         OPT(register_coalesce);
+         OPT(compute_to_mrf);
       } while (progress);
 
+      if (lower_load_payload()) {
+         register_coalesce();
+         dead_code_eliminate();
+      }
+
       lower_uniform_pull_constant_loads();
 
       assign_curb_setup();
@@ -3464,6 +3125,10 @@ fs_visitor::run()
          if (dispatch_width == 16) {
             fail("Failure to register allocate.  Reduce number of "
                  "live scalar values to avoid this.");
+         } else {
+            perf_debug("Fragment shader triggered register spilling.  "
+                       "Try reducing the number of live scalar values to "
+                       "improve performance.\n");
          }
 
          /* Since we're out of heuristics, just go spill registers until we
@@ -3489,10 +3154,14 @@ fs_visitor::run()
    if (!allocated_without_spills)
       schedule_instructions(SCHEDULE_POST);
 
+   if (last_scratch > 0) {
+      prog_data->total_scratch = brw_get_scratch_size(last_scratch);
+   }
+
    if (dispatch_width == 8)
-      c->prog_data.reg_blocks = brw_register_blocks(grf_used);
+      prog_data->reg_blocks = brw_register_blocks(grf_used);
    else
-      c->prog_data.reg_blocks_16 = brw_register_blocks(grf_used);
+      prog_data->reg_blocks_16 = brw_register_blocks(grf_used);
 
    /* If any state parameters were appended, then ParameterValues could have
     * been realloced, in which case the driver uniform storage set up by
@@ -3505,7 +3174,10 @@ fs_visitor::run()
 }
 
 const unsigned *
-brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c,
+brw_wm_fs_emit(struct brw_context *brw,
+               void *mem_ctx,
+               const struct brw_wm_prog_key *key,
+               struct brw_wm_prog_data *prog_data,
                struct gl_fragment_program *fp,
                struct gl_shader_program *prog,
                unsigned *final_assembly_size)
@@ -3528,7 +3200,7 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c,
 
    /* Now the main event: Visit the shader IR and generate our FS IR for it.
     */
-   fs_visitor v(brw, c, prog, fp, 8);
+   fs_visitor v(brw, mem_ctx, key, prog_data, prog, fp, 8);
    if (!v.run()) {
       if (prog) {
          prog->LinkStatus = false;
@@ -3542,7 +3214,7 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c,
    }
 
    exec_list *simd16_instructions = NULL;
-   fs_visitor v2(brw, c, prog, fp, 16);
+   fs_visitor v2(brw, mem_ctx, key, prog_data, prog, fp, 16);
    if (brw->gen >= 5 && likely(!(INTEL_DEBUG & DEBUG_NO16))) {
       if (!v.simd16_unsupported) {
          /* Try a SIMD16 compile */
@@ -3561,18 +3233,19 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c,
 
    const unsigned *assembly = NULL;
    if (brw->gen >= 8) {
-      gen8_fs_generator g(brw, c, prog, fp, v.dual_src_output.file != BAD_FILE);
+      gen8_fs_generator g(brw, mem_ctx, key, prog_data, prog, fp, v.do_dual_src);
       assembly = g.generate_assembly(&v.instructions, simd16_instructions,
                                      final_assembly_size);
    } else {
-      fs_generator g(brw, c, prog, fp, v.dual_src_output.file != BAD_FILE);
+      fs_generator g(brw, mem_ctx, key, prog_data, prog, fp, v.do_dual_src,
+                     v.runtime_check_aads_emit, INTEL_DEBUG & DEBUG_WM);
       assembly = g.generate_assembly(&v.instructions, simd16_instructions,
                                      final_assembly_size);
    }
 
    if (unlikely(brw->perf_debug) && shader) {
       if (shader->compiled_once)
-         brw_wm_debug_recompile(brw, prog, &c->key);
+         brw_wm_debug_recompile(brw, prog, key);
       shader->compiled_once = true;
 
       if (start_busy && !drm_intel_bo_busy(brw->batch.last_bo)) {
@@ -3616,8 +3289,6 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog)
                                          BRW_FS_VARYING_INPUT_MASK) > 16)
       key.input_slots_valid = fp->Base.InputsRead | VARYING_BIT_POS;
 
-   key.clamp_fragment_color = ctx->API == API_OPENGL_COMPAT;
-
    unsigned sampler_count = _mesa_fls(fp->Base.SamplersUsed);
    for (unsigned i = 0; i < sampler_count; i++) {
       if (fp->Base.ShadowSamplers & (1 << i)) {