radeonsi: Add function for converting LLVM type to intrinsic string
[mesa.git] / src / gallium / drivers / radeonsi / si_shader.c
index 12f2df9bfe09d3fe9235ab36e55a63c2ccda3508..4e07317f06e87c2c18060461581246cdb1be22d1 100644 (file)
 #include "gallivm/lp_bld_intr.h"
 #include "gallivm/lp_bld_logic.h"
 #include "gallivm/lp_bld_arit.h"
-#include "gallivm/lp_bld_bitarit.h"
 #include "gallivm/lp_bld_flow.h"
 #include "gallivm/lp_bld_misc.h"
-#include "radeon/r600_cs.h"
 #include "radeon/radeon_llvm.h"
 #include "radeon/radeon_elf_util.h"
 #include "radeon/radeon_llvm_emit.h"
 #include "util/u_memory.h"
 #include "util/u_string.h"
-#include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_build.h"
 #include "tgsi/tgsi_util.h"
 #include "tgsi/tgsi_dump.h"
 
 #include "si_pipe.h"
-#include "si_shader.h"
 #include "sid.h"
 
-#include <errno.h>
 
 static const char *scratch_rsrc_dword0_symbol =
        "SCRATCH_RSRC_DWORD0";
@@ -105,17 +100,11 @@ struct si_shader_context
        unsigned uniform_md_kind;
        LLVMValueRef empty_md;
 
-       LLVMValueRef const_buffers[SI_NUM_CONST_BUFFERS];
-       LLVMValueRef lds;
-       LLVMValueRef *constants[SI_NUM_CONST_BUFFERS];
-       LLVMValueRef shader_buffers[SI_NUM_SHADER_BUFFERS];
-       LLVMValueRef sampler_views[SI_NUM_SAMPLERS];
-       LLVMValueRef sampler_states[SI_NUM_SAMPLERS];
-       LLVMValueRef fmasks[SI_NUM_SAMPLERS];
-       LLVMValueRef images[SI_NUM_IMAGES];
-       LLVMValueRef so_buffers[4];
+       /* Preloaded descriptors. */
        LLVMValueRef esgs_ring;
        LLVMValueRef gsvs_ring[4];
+
+       LLVMValueRef lds;
        LLVMValueRef gs_next_vertex[4];
        LLVMValueRef return_value;
 
@@ -163,18 +152,10 @@ static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
  */
 #define VS_EPILOG_PRIMID_LOC 2
 
-#define PERSPECTIVE_BASE 0
-#define LINEAR_BASE 9
-
-#define SAMPLE_OFFSET 0
-#define CENTER_OFFSET 2
-#define CENTROID_OFSET 4
-
-#define USE_SGPR_MAX_SUFFIX_LEN 5
-#define CONST_ADDR_SPACE 2
-#define LOCAL_ADDR_SPACE 3
-#define USER_SGPR_ADDR_SPACE 8
-
+enum {
+       CONST_ADDR_SPACE = 2,
+       LOCAL_ADDR_SPACE = 3,
+};
 
 #define SENDMSG_GS 2
 #define SENDMSG_GS_DONE 3
@@ -369,19 +350,26 @@ get_tcs_out_current_patch_data_offset(struct si_shader_context *ctx)
                            "");
 }
 
+static LLVMValueRef build_gep0(struct si_shader_context *ctx,
+                              LLVMValueRef base_ptr, LLVMValueRef index)
+{
+       LLVMValueRef indices[2] = {
+               LLVMConstInt(ctx->i32, 0, 0),
+               index,
+       };
+       return LLVMBuildGEP(ctx->radeon_bld.gallivm.builder, base_ptr,
+                           indices, 2, "");
+}
+
 static void build_indexed_store(struct si_shader_context *ctx,
                                LLVMValueRef base_ptr, LLVMValueRef index,
                                LLVMValueRef value)
 {
        struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
        struct gallivm_state *gallivm = bld_base->base.gallivm;
-       LLVMValueRef indices[2], pointer;
-
-       indices[0] = bld_base->uint_bld.zero;
-       indices[1] = index;
 
-       pointer = LLVMBuildGEP(gallivm->builder, base_ptr, indices, 2, "");
-       LLVMBuildStore(gallivm->builder, value, pointer);
+       LLVMBuildStore(gallivm->builder, value,
+                      build_gep0(ctx, base_ptr, index));
 }
 
 /**
@@ -399,12 +387,9 @@ static LLVMValueRef build_indexed_load(struct si_shader_context *ctx,
 {
        struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
        struct gallivm_state *gallivm = bld_base->base.gallivm;
-       LLVMValueRef indices[2], pointer;
-
-       indices[0] = bld_base->uint_bld.zero;
-       indices[1] = index;
+       LLVMValueRef pointer;
 
-       pointer = LLVMBuildGEP(gallivm->builder, base_ptr, indices, 2, "");
+       pointer = build_gep0(ctx, base_ptr, index);
        if (uniform)
                LLVMSetMetadata(pointer, ctx->uniform_md_kind, ctx->empty_md);
        return LLVMBuildLoad(gallivm->builder, pointer, "");
@@ -446,7 +431,8 @@ static LLVMValueRef get_instance_index_for_fetch(
 static void declare_input_vs(
        struct radeon_llvm_context *radeon_bld,
        unsigned input_index,
-       const struct tgsi_full_declaration *decl)
+       const struct tgsi_full_declaration *decl,
+       LLVMValueRef out[4])
 {
        struct lp_build_context *base = &radeon_bld->soa.bld_base.base;
        struct gallivm_state *gallivm = base->gallivm;
@@ -504,11 +490,8 @@ static void declare_input_vs(
        /* Break up the vec4 into individual components */
        for (chan = 0; chan < 4; chan++) {
                LLVMValueRef llvm_chan = lp_build_const_int32(gallivm, chan);
-               /* XXX: Use a helper function for this.  There is one in
-                * tgsi_llvm.c. */
-               ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, chan)] =
-                               LLVMBuildExtractElement(gallivm->builder,
-                               input, llvm_chan, "");
+               out[chan] = LLVMBuildExtractElement(gallivm->builder,
+                                                   input, llvm_chan, "");
        }
 }
 
@@ -1469,7 +1452,8 @@ static LLVMValueRef get_interp_param(struct si_shader_context *ctx,
 static void declare_input_fs(
        struct radeon_llvm_context *radeon_bld,
        unsigned input_index,
-       const struct tgsi_full_declaration *decl)
+       const struct tgsi_full_declaration *decl,
+       LLVMValueRef out[4])
 {
        struct lp_build_context *base = &radeon_bld->soa.bld_base.base;
        struct si_shader_context *ctx =
@@ -1488,14 +1472,10 @@ static void declare_input_fs(
                unsigned offset = SI_PARAM_POS_FIXED_PT + 1 +
                                  (i ? util_bitcount(colors_read & 0xf) : 0);
 
-               radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)] =
-                       mask & 0x1 ? LLVMGetParam(main_fn, offset++) : base->undef;
-               radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 1)] =
-                       mask & 0x2 ? LLVMGetParam(main_fn, offset++) : base->undef;
-               radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 2)] =
-                       mask & 0x4 ? LLVMGetParam(main_fn, offset++) : base->undef;
-               radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 3)] =
-                       mask & 0x8 ? LLVMGetParam(main_fn, offset++) : base->undef;
+               out[0] = mask & 0x1 ? LLVMGetParam(main_fn, offset++) : base->undef;
+               out[1] = mask & 0x2 ? LLVMGetParam(main_fn, offset++) : base->undef;
+               out[2] = mask & 0x4 ? LLVMGetParam(main_fn, offset++) : base->undef;
+               out[3] = mask & 0x8 ? LLVMGetParam(main_fn, offset++) : base->undef;
                return;
        }
 
@@ -1519,7 +1499,7 @@ static void declare_input_fs(
                        shader->selector->info.colors_read, interp_param,
                        LLVMGetParam(main_fn, SI_PARAM_PRIM_MASK),
                        LLVMGetParam(main_fn, SI_PARAM_FRONT_FACE),
-                       &radeon_bld->inputs[radeon_llvm_reg_index_soa(input_index, 0)]);
+                       &out[0]);
 }
 
 static LLVMValueRef get_sample_id(struct radeon_llvm_context *radeon_bld)
@@ -1730,7 +1710,12 @@ static void declare_system_value(
        }
 
        case TGSI_SEMANTIC_VERTICESIN:
-               value = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 26, 6);
+               if (ctx->type == PIPE_SHADER_TESS_CTRL)
+                       value = unpack_param(ctx, SI_PARAM_TCS_OUT_LAYOUT, 26, 6);
+               else if (ctx->type == PIPE_SHADER_TESS_EVAL)
+                       value = unpack_param(ctx, SI_PARAM_TCS_OFFCHIP_LAYOUT, 9, 7);
+               else
+                       assert(!"invalid shader stage for TGSI_SEMANTIC_VERTICESIN");
                break;
 
        case TGSI_SEMANTIC_TESSINNER:
@@ -1785,16 +1770,21 @@ static void declare_system_value(
                LLVMValueRef values[3];
                unsigned i;
                unsigned *properties = ctx->shader->selector->info.properties;
-               unsigned sizes[3] = {
-                       properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH],
-                       properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT],
-                       properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH]
-               };
 
-               for (i = 0; i < 3; ++i)
-                       values[i] = lp_build_const_int32(gallivm, sizes[i]);
+               if (properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] != 0) {
+                       unsigned sizes[3] = {
+                               properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH],
+                               properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT],
+                               properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH]
+                       };
+
+                       for (i = 0; i < 3; ++i)
+                               values[i] = lp_build_const_int32(gallivm, sizes[i]);
 
-               value = lp_build_gather_values(gallivm, values, 3);
+                       value = lp_build_gather_values(gallivm, values, 3);
+               } else {
+                       value = LLVMGetParam(radeon_bld->main_fn, SI_PARAM_BLOCK_SIZE);
+               }
                break;
        }
 
@@ -1849,6 +1839,15 @@ static void declare_compute_memory(struct radeon_llvm_context *radeon_bld,
        ctx->shared_memory = LLVMBuildBitCast(gallivm->builder, var, i8p, "");
 }
 
+static LLVMValueRef load_const_buffer_desc(struct si_shader_context *ctx, int i)
+{
+       LLVMValueRef list_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
+                                            SI_PARAM_CONST_BUFFERS);
+
+       return build_indexed_load_const(ctx, list_ptr,
+                                       LLVMConstInt(ctx->i32, i, 0));
+}
+
 static LLVMValueRef fetch_constant(
        struct lp_build_tgsi_context *bld_base,
        const struct tgsi_full_src_register *reg,
@@ -1876,12 +1875,20 @@ static LLVMValueRef fetch_constant(
        idx = reg->Register.Index * 4 + swizzle;
 
        if (!reg->Register.Indirect && !reg->Dimension.Indirect) {
+               LLVMValueRef c0, c1, desc;
+
+               desc = load_const_buffer_desc(ctx, buf);
+               c0 = buffer_load_const(ctx, desc,
+                                      LLVMConstInt(ctx->i32, idx * 4, 0));
+
                if (!tgsi_type_is_64bit(type))
-                       return bitcast(bld_base, type, ctx->constants[buf][idx]);
+                       return bitcast(bld_base, type, c0);
                else {
+                       c1 = buffer_load_const(ctx, desc,
+                                              LLVMConstInt(ctx->i32,
+                                                           (idx + 1) * 4, 0));
                        return radeon_llvm_emit_fetch_64bit(bld_base, type,
-                                                           ctx->constants[buf][idx],
-                                                           ctx->constants[buf][idx + 1]);
+                                                           c0, c1);
                }
        }
 
@@ -1893,7 +1900,7 @@ static LLVMValueRef fetch_constant(
                                                   SI_NUM_CONST_BUFFERS);
                bufp = build_indexed_load_const(ctx, ptr, index);
        } else
-               bufp = ctx->const_buffers[buf];
+               bufp = load_const_buffer_desc(ctx, buf);
 
        addr = ctx->radeon_bld.soa.addr[ireg->Index][ireg->Swizzle];
        addr = LLVMBuildLoad(base->gallivm->builder, addr, "load addr reg");
@@ -1913,8 +1920,7 @@ static LLVMValueRef fetch_constant(
                addr2 = lp_build_add(&bld_base->uint_bld, addr2,
                                     lp_build_const_int32(base->gallivm, idx * 4));
 
-               result2 = buffer_load_const(ctx, ctx->const_buffers[buf],
-                                           addr2);
+               result2 = buffer_load_const(ctx, bufp, addr2);
 
                result = radeon_llvm_emit_fetch_64bit(bld_base, type,
                                                      result, result2);
@@ -2261,6 +2267,19 @@ static void si_llvm_emit_streamout(struct si_shader_context *ctx,
        LLVMBuilderRef builder = gallivm->builder;
        int i, j;
        struct lp_build_if_state if_ctx;
+       LLVMValueRef so_buffers[4];
+       LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
+                                           SI_PARAM_RW_BUFFERS);
+
+       /* Load the descriptors. */
+       for (i = 0; i < 4; ++i) {
+               if (ctx->shader->selector->so.stride[i]) {
+                       LLVMValueRef offset = lp_build_const_int32(gallivm,
+                                                                  SI_VS_STREAMOUT_BUF0 + i);
+
+                       so_buffers[i] = build_indexed_load_const(ctx, buf_ptr, offset);
+               }
+       }
 
        /* Get bits [22:16], i.e. (so_param >> 16) & 127; */
        LLVMValueRef so_vtx_count =
@@ -2356,7 +2375,7 @@ static void si_llvm_emit_streamout(struct si_shader_context *ctx,
                                              lp_build_const_int32(gallivm, stream), "");
 
                        lp_build_if(&if_ctx_stream, gallivm, can_emit_stream);
-                       build_tbuffer_store_dwords(ctx, ctx->so_buffers[buf_idx],
+                       build_tbuffer_store_dwords(ctx, so_buffers[buf_idx],
                                                   vdata, num_comps,
                                                   so_write_offset[buf_idx],
                                                   LLVMConstInt(ctx->i32, 0, 0),
@@ -2917,6 +2936,25 @@ struct si_ps_exports {
        LLVMValueRef args[10][9];
 };
 
+unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
+                                   bool writes_samplemask)
+{
+       if (writes_z) {
+               /* Z needs 32 bits. */
+               if (writes_samplemask)
+                       return V_028710_SPI_SHADER_32_ABGR;
+               else if (writes_stencil)
+                       return V_028710_SPI_SHADER_32_GR;
+               else
+                       return V_028710_SPI_SHADER_32_R;
+       } else if (writes_stencil || writes_samplemask) {
+               /* Both stencil and sample mask need only 16 bits. */
+               return V_028710_SPI_SHADER_UINT16_ABGR;
+       } else {
+               return V_028710_SPI_SHADER_ZERO;
+       }
+}
+
 static void si_export_mrt_z(struct lp_build_tgsi_context *bld_base,
                            LLVMValueRef depth, LLVMValueRef stencil,
                            LLVMValueRef samplemask, struct si_ps_exports *exp)
@@ -2926,6 +2964,9 @@ static void si_export_mrt_z(struct lp_build_tgsi_context *bld_base,
        struct lp_build_context *uint = &bld_base->uint_bld;
        LLVMValueRef args[9];
        unsigned mask = 0;
+       unsigned format = si_get_spi_shader_z_format(depth != NULL,
+                                                    stencil != NULL,
+                                                    samplemask != NULL);
 
        assert(depth || stencil || samplemask);
 
@@ -2941,19 +2982,36 @@ static void si_export_mrt_z(struct lp_build_tgsi_context *bld_base,
        args[7] = base->undef; /* B, sample mask */
        args[8] = base->undef; /* A, alpha to mask */
 
-       if (depth) {
-               args[5] = depth;
-               mask |= 0x1;
-       }
-
-       if (stencil) {
-               args[6] = stencil;
-               mask |= 0x2;
-       }
+       if (format == V_028710_SPI_SHADER_UINT16_ABGR) {
+               assert(!depth);
+               args[4] = uint->one; /* COMPR flag */
 
-       if (samplemask) {
-               args[7] = samplemask;
-               mask |= 0x4;
+               if (stencil) {
+                       /* Stencil should be in X[23:16]. */
+                       stencil = bitcast(bld_base, TGSI_TYPE_UNSIGNED, stencil);
+                       stencil = LLVMBuildShl(base->gallivm->builder, stencil,
+                                              LLVMConstInt(ctx->i32, 16, 0), "");
+                       args[5] = bitcast(bld_base, TGSI_TYPE_FLOAT, stencil);
+                       mask |= 0x3;
+               }
+               if (samplemask) {
+                       /* SampleMask should be in Y[15:0]. */
+                       args[6] = samplemask;
+                       mask |= 0xc;
+               }
+       } else {
+               if (depth) {
+                       args[5] = depth;
+                       mask |= 0x1;
+               }
+               if (stencil) {
+                       args[6] = stencil;
+                       mask |= 0x2;
+               }
+               if (samplemask) {
+                       args[7] = samplemask;
+                       mask |= 0x4;
+               }
        }
 
        /* SI (except OLAND) has a bug that it only looks
@@ -3056,10 +3114,10 @@ static void si_export_null(struct lp_build_tgsi_context *bld_base)
        args[2] = uint->one; /* DONE bit */
        args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_NULL);
        args[4] = uint->zero; /* COMPR flag (0 = 32-bit export) */
-       args[5] = uint->undef; /* R */
-       args[6] = uint->undef; /* G */
-       args[7] = uint->undef; /* B */
-       args[8] = uint->undef; /* A */
+       args[5] = base->undef; /* R */
+       args[6] = base->undef; /* G */
+       args[7] = base->undef; /* B */
+       args[8] = base->undef; /* A */
 
        lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
                           ctx->voidt, args, 9, 0);
@@ -3289,17 +3347,39 @@ static LLVMValueRef get_buffer_size(
  * Given the i32 or vNi32 \p type, generate the textual name (e.g. for use with
  * intrinsic names).
  */
-static void build_int_type_name(
+static void build_type_name_for_intr(
        LLVMTypeRef type,
        char *buf, unsigned bufsize)
 {
-       assert(bufsize >= 6);
+       LLVMTypeRef elem_type = type;
 
-       if (LLVMGetTypeKind(type) == LLVMVectorTypeKind)
-               snprintf(buf, bufsize, "v%ui32",
-                        LLVMGetVectorSize(type));
-       else
-               strcpy(buf, "i32");
+       assert(bufsize >= 8);
+
+       if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) {
+               int ret = snprintf(buf, bufsize, "v%u",
+                                       LLVMGetVectorSize(type));
+               if (ret < 0) {
+                       char *type_name = LLVMPrintTypeToString(type);
+                       fprintf(stderr, "Error building type name for: %s\n",
+                               type_name);
+                       return;
+               }
+               elem_type = LLVMGetElementType(type);
+               buf += ret;
+               bufsize -= ret;
+       }
+       switch (LLVMGetTypeKind(elem_type)) {
+       default: break;
+       case LLVMIntegerTypeKind:
+               snprintf(buf, bufsize, "i%d", LLVMGetIntTypeWidth(elem_type));
+               break;
+       case LLVMFloatTypeKind:
+               snprintf(buf, bufsize, "f32");
+               break;
+       case LLVMDoubleTypeKind:
+               snprintf(buf, bufsize, "f64");
+               break;
+       }
 }
 
 static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
@@ -3343,18 +3423,18 @@ static LLVMValueRef
 shader_buffer_fetch_rsrc(struct si_shader_context *ctx,
                         const struct tgsi_full_src_register *reg)
 {
-       LLVMValueRef ind_index;
-       LLVMValueRef rsrc_ptr;
+       LLVMValueRef index;
+       LLVMValueRef rsrc_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
+                                            SI_PARAM_SHADER_BUFFERS);
 
        if (!reg->Register.Indirect)
-               return ctx->shader_buffers[reg->Register.Index];
-
-       ind_index = get_bounded_indirect_index(ctx, &reg->Indirect,
-                                              reg->Register.Index,
-                                              SI_NUM_SHADER_BUFFERS);
+               index = LLVMConstInt(ctx->i32, reg->Register.Index, 0);
+       else
+               index = get_bounded_indirect_index(ctx, &reg->Indirect,
+                                                  reg->Register.Index,
+                                                  SI_NUM_SHADER_BUFFERS);
 
-       rsrc_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_SHADER_BUFFERS);
-       return build_indexed_load_const(ctx, rsrc_ptr, ind_index);
+       return build_indexed_load_const(ctx, rsrc_ptr, index);
 }
 
 static bool tgsi_is_array_sampler(unsigned target)
@@ -3417,18 +3497,21 @@ image_fetch_rsrc(
        LLVMValueRef *rsrc)
 {
        struct si_shader_context *ctx = si_shader_context(bld_base);
+       LLVMValueRef rsrc_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
+                                            SI_PARAM_IMAGES);
+       LLVMValueRef index, tmp;
 
        assert(image->Register.File == TGSI_FILE_IMAGE);
 
        if (!image->Register.Indirect) {
-               /* Fast path: use preloaded resources */
-               *rsrc = ctx->images[image->Register.Index];
-       } else {
-               /* Indexing and manual load */
-               LLVMValueRef ind_index;
-               LLVMValueRef rsrc_ptr;
-               LLVMValueRef tmp;
+               const struct tgsi_shader_info *info = bld_base->info;
+
+               index = LLVMConstInt(ctx->i32, image->Register.Index, 0);
 
+               if (info->images_writemask & (1 << image->Register.Index) &&
+                   !(info->images_buffers & (1 << image->Register.Index)))
+                       dcc_off = true;
+       } else {
                /* From the GL_ARB_shader_image_load_store extension spec:
                 *
                 *    If a shader performs an image load, store, or atomic
@@ -3438,16 +3521,15 @@ image_fetch_rsrc(
                 *    array, the results of the operation are undefined but may
                 *    not lead to termination.
                 */
-               ind_index = get_bounded_indirect_index(ctx, &image->Indirect,
-                                                      image->Register.Index,
-                                                      SI_NUM_IMAGES);
-
-               rsrc_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_IMAGES);
-               tmp = build_indexed_load_const(ctx, rsrc_ptr, ind_index);
-               if (dcc_off)
-                       tmp = force_dcc_off(ctx, tmp);
-               *rsrc = tmp;
+               index = get_bounded_indirect_index(ctx, &image->Indirect,
+                                                  image->Register.Index,
+                                                  SI_NUM_IMAGES);
        }
+
+       tmp = build_indexed_load_const(ctx, rsrc_ptr, index);
+       if (dcc_off)
+               tmp = force_dcc_off(ctx, tmp);
+       *rsrc = tmp;
 }
 
 static LLVMValueRef image_fetch_coords(
@@ -3678,6 +3760,18 @@ static void load_emit_memory(
        emit_data->output[emit_data->chan] = lp_build_gather_values(gallivm, channels, 4);
 }
 
+static void get_image_intr_name(const char *base_name,
+                               LLVMTypeRef coords_type,
+                               char *out_name, unsigned out_len)
+{
+       char coords_type_name[8];
+
+       build_type_name_for_intr(coords_type, coords_type_name,
+                           sizeof(coords_type_name));
+
+       snprintf(out_name, out_len, "%s.%s", base_name, coords_type_name);
+}
+
 static void load_emit(
                const struct lp_build_tgsi_action *action,
                struct lp_build_tgsi_context *bld_base,
@@ -3688,7 +3782,6 @@ static void load_emit(
        LLVMBuilderRef builder = gallivm->builder;
        const struct tgsi_full_instruction * inst = emit_data->inst;
        char intrinsic_name[32];
-       char coords_type[8];
 
        if (inst->Src[0].Register.File == TGSI_FILE_MEMORY) {
                load_emit_memory(ctx, emit_data);
@@ -3710,11 +3803,9 @@ static void load_emit(
                                emit_data->args, emit_data->arg_count,
                                LLVMReadOnlyAttribute);
        } else {
-               build_int_type_name(LLVMTypeOf(emit_data->args[0]),
-                                   coords_type, sizeof(coords_type));
-
-               snprintf(intrinsic_name, sizeof(intrinsic_name),
-                        "llvm.amdgcn.image.load.%s", coords_type);
+               get_image_intr_name("llvm.amdgcn.image.load",
+                               LLVMTypeOf(emit_data->args[0]),
+                               intrinsic_name, sizeof(intrinsic_name));
 
                emit_data->output[emit_data->chan] =
                        lp_build_intrinsic(
@@ -3891,7 +3982,6 @@ static void store_emit(
        const struct tgsi_full_instruction * inst = emit_data->inst;
        unsigned target = inst->Memory.Texture;
        char intrinsic_name[32];
-       char coords_type[8];
 
        if (inst->Dst[0].Register.File == TGSI_FILE_MEMORY) {
                store_emit_memory(ctx, emit_data);
@@ -3912,10 +4002,9 @@ static void store_emit(
                        emit_data->dst_type, emit_data->args,
                        emit_data->arg_count, 0);
        } else {
-               build_int_type_name(LLVMTypeOf(emit_data->args[1]),
-                                   coords_type, sizeof(coords_type));
-               snprintf(intrinsic_name, sizeof(intrinsic_name),
-                        "llvm.amdgcn.image.store.%s", coords_type);
+               get_image_intr_name("llvm.amdgcn.image.store",
+                               LLVMTypeOf(emit_data->args[1]),
+                               intrinsic_name, sizeof(intrinsic_name));
 
                emit_data->output[emit_data->chan] =
                        lp_build_intrinsic(
@@ -4077,7 +4166,7 @@ static void atomic_emit(
        } else {
                char coords_type[8];
 
-               build_int_type_name(LLVMTypeOf(emit_data->args[1]),
+               build_type_name_for_intr(LLVMTypeOf(emit_data->args[1]),
                                    coords_type, sizeof(coords_type));
                snprintf(intrinsic_name, sizeof(intrinsic_name),
                         "llvm.amdgcn.image.atomic.%s.%s",
@@ -4100,7 +4189,7 @@ static void resq_fetch_args(
        const struct tgsi_full_instruction *inst = emit_data->inst;
        const struct tgsi_full_src_register *reg = &inst->Src[0];
 
-       emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4);
+       emit_data->dst_type = ctx->v4i32;
 
        if (reg->Register.File == TGSI_FILE_BUFFER) {
                emit_data->args[0] = shader_buffer_fetch_rsrc(ctx, reg);
@@ -4151,9 +4240,7 @@ static void resq_emit(
                        LLVMValueRef imm6 = lp_build_const_int32(gallivm, 6);
 
                        LLVMValueRef z = LLVMBuildExtractElement(builder, out, imm2, "");
-                       z = LLVMBuildBitCast(builder, z, bld_base->uint_bld.elem_type, "");
                        z = LLVMBuildSDiv(builder, z, imm6, "");
-                       z = LLVMBuildBitCast(builder, z, bld_base->base.elem_type, "");
                        out = LLVMBuildInsertElement(builder, out, z, imm2, "");
                }
        }
@@ -4224,9 +4311,9 @@ static LLVMTypeRef const_array(LLVMTypeRef elem_type, int num_elements)
 /**
  * Load an image view, fmask view. or sampler state descriptor.
  */
-static LLVMValueRef get_sampler_desc_custom(struct si_shader_context *ctx,
-                                           LLVMValueRef list, LLVMValueRef index,
-                                           enum desc_type type)
+static LLVMValueRef load_sampler_desc_custom(struct si_shader_context *ctx,
+                                            LLVMValueRef list, LLVMValueRef index,
+                                            enum desc_type type)
 {
        struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
        LLVMBuilderRef builder = gallivm->builder;
@@ -4253,13 +4340,13 @@ static LLVMValueRef get_sampler_desc_custom(struct si_shader_context *ctx,
        return build_indexed_load_const(ctx, list, index);
 }
 
-static LLVMValueRef get_sampler_desc(struct si_shader_context *ctx,
+static LLVMValueRef load_sampler_desc(struct si_shader_context *ctx,
                                     LLVMValueRef index, enum desc_type type)
 {
        LLVMValueRef list = LLVMGetParam(ctx->radeon_bld.main_fn,
                                         SI_PARAM_SAMPLERS);
 
-       return get_sampler_desc_custom(ctx, list, index, type);
+       return load_sampler_desc_custom(ctx, list, index, type);
 }
 
 /* Disable anisotropic filtering if BASE_LEVEL == LAST_LEVEL.
@@ -4301,41 +4388,37 @@ static void tex_fetch_ptrs(
        unsigned target = inst->Texture.Texture;
        unsigned sampler_src;
        unsigned sampler_index;
+       LLVMValueRef index;
 
        sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
        sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
 
        if (emit_data->inst->Src[sampler_src].Register.Indirect) {
                const struct tgsi_full_src_register *reg = &emit_data->inst->Src[sampler_src];
-               LLVMValueRef ind_index;
 
-               ind_index = get_bounded_indirect_index(ctx,
-                                                      &reg->Indirect,
-                                                      reg->Register.Index,
-                                                      SI_NUM_SAMPLERS);
+               index = get_bounded_indirect_index(ctx,
+                                                  &reg->Indirect,
+                                                  reg->Register.Index,
+                                                  SI_NUM_SAMPLERS);
+       } else {
+               index = LLVMConstInt(ctx->i32, sampler_index, 0);
+       }
 
-               *res_ptr = get_sampler_desc(ctx, ind_index, DESC_IMAGE);
+       *res_ptr = load_sampler_desc(ctx, index, DESC_IMAGE);
 
-               if (target == TGSI_TEXTURE_2D_MSAA ||
-                   target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
-                       if (samp_ptr)
-                               *samp_ptr = NULL;
-                       if (fmask_ptr)
-                               *fmask_ptr = get_sampler_desc(ctx, ind_index, DESC_FMASK);
-               } else {
-                       if (samp_ptr) {
-                               *samp_ptr = get_sampler_desc(ctx, ind_index, DESC_SAMPLER);
-                               *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
-                       }
-                       if (fmask_ptr)
-                               *fmask_ptr = NULL;
-               }
-       } else {
-               *res_ptr = ctx->sampler_views[sampler_index];
+       if (target == TGSI_TEXTURE_2D_MSAA ||
+           target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
                if (samp_ptr)
-                       *samp_ptr = ctx->sampler_states[sampler_index];
+                       *samp_ptr = NULL;
+               if (fmask_ptr)
+                       *fmask_ptr = load_sampler_desc(ctx, index, DESC_FMASK);
+       } else {
+               if (samp_ptr) {
+                       *samp_ptr = load_sampler_desc(ctx, index, DESC_SAMPLER);
+                       *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
+               }
                if (fmask_ptr)
-                       *fmask_ptr = ctx->fmasks[sampler_index];
+                       *fmask_ptr = NULL;
        }
 }
 
@@ -4721,16 +4804,86 @@ static void tex_fetch_args(
                           samp_ptr, address, count, dmask);
 }
 
+/* Gather4 should follow the same rules as bilinear filtering, but the hardware
+ * incorrectly forces nearest filtering if the texture format is integer.
+ * The only effect it has on Gather4, which always returns 4 texels for
+ * bilinear filtering, is that the final coordinates are off by 0.5 of
+ * the texel size.
+ *
+ * The workaround is to subtract 0.5 from the unnormalized coordinates,
+ * or (0.5 / size) from the normalized coordinates.
+ */
+static void si_lower_gather4_integer(struct si_shader_context *ctx,
+                                    struct lp_build_emit_data *emit_data,
+                                    const char *intr_name,
+                                    unsigned coord_vgpr_index)
+{
+       LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
+       LLVMValueRef coord = emit_data->args[0];
+       LLVMValueRef half_texel[2];
+       int c;
+
+       if (emit_data->inst->Texture.Texture == TGSI_TEXTURE_RECT ||
+           emit_data->inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT) {
+               half_texel[0] = half_texel[1] = LLVMConstReal(ctx->f32, -0.5);
+       } else {
+               struct tgsi_full_instruction txq_inst = {};
+               struct lp_build_emit_data txq_emit_data = {};
+
+               /* Query the texture size. */
+               txq_inst.Texture.Texture = emit_data->inst->Texture.Texture;
+               txq_emit_data.inst = &txq_inst;
+               txq_emit_data.dst_type = ctx->v4i32;
+               set_tex_fetch_args(ctx, &txq_emit_data, TGSI_OPCODE_TXQ,
+                                  txq_inst.Texture.Texture,
+                                  emit_data->args[1], NULL,
+                                  &ctx->radeon_bld.soa.bld_base.uint_bld.zero,
+                                  1, 0xf);
+               txq_emit(NULL, &ctx->radeon_bld.soa.bld_base, &txq_emit_data);
+
+               /* Compute -0.5 / size. */
+               for (c = 0; c < 2; c++) {
+                       half_texel[c] =
+                               LLVMBuildExtractElement(builder, txq_emit_data.output[0],
+                                                       LLVMConstInt(ctx->i32, c, 0), "");
+                       half_texel[c] = LLVMBuildUIToFP(builder, half_texel[c], ctx->f32, "");
+                       half_texel[c] =
+                               lp_build_emit_llvm_unary(&ctx->radeon_bld.soa.bld_base,
+                                                        TGSI_OPCODE_RCP, half_texel[c]);
+                       half_texel[c] = LLVMBuildFMul(builder, half_texel[c],
+                                                     LLVMConstReal(ctx->f32, -0.5), "");
+               }
+       }
+
+       for (c = 0; c < 2; c++) {
+               LLVMValueRef tmp;
+               LLVMValueRef index = LLVMConstInt(ctx->i32, coord_vgpr_index + c, 0);
+
+               tmp = LLVMBuildExtractElement(builder, coord, index, "");
+               tmp = LLVMBuildBitCast(builder, tmp, ctx->f32, "");
+               tmp = LLVMBuildFAdd(builder, tmp, half_texel[c], "");
+               tmp = LLVMBuildBitCast(builder, tmp, ctx->i32, "");
+               coord = LLVMBuildInsertElement(builder, coord, tmp, index, "");
+       }
+
+       emit_data->args[0] = coord;
+       emit_data->output[emit_data->chan] =
+               lp_build_intrinsic(builder, intr_name, emit_data->dst_type,
+                                  emit_data->args, emit_data->arg_count,
+                                  LLVMReadNoneAttribute);
+}
+
 static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
                                struct lp_build_tgsi_context *bld_base,
                                struct lp_build_emit_data *emit_data)
 {
        struct si_shader_context *ctx = si_shader_context(bld_base);
        struct lp_build_context *base = &bld_base->base;
-       unsigned opcode = emit_data->inst->Instruction.Opcode;
-       unsigned target = emit_data->inst->Texture.Texture;
+       const struct tgsi_full_instruction *inst = emit_data->inst;
+       unsigned opcode = inst->Instruction.Opcode;
+       unsigned target = inst->Texture.Texture;
        char intr_name[127];
-       bool has_offset = emit_data->inst->Texture.NumOffsets > 0;
+       bool has_offset = inst->Texture.NumOffsets > 0;
        bool is_shadow = tgsi_is_shadow_target(target);
        char type[64];
        const char *name = "llvm.SI.image.sample";
@@ -4787,11 +4940,34 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
        }
 
        /* Add the type and suffixes .c, .o if needed. */
-       build_int_type_name(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
+       build_type_name_for_intr(LLVMTypeOf(emit_data->args[0]), type, sizeof(type));
        sprintf(intr_name, "%s%s%s%s.%s",
                name, is_shadow ? ".c" : "", infix,
                has_offset ? ".o" : "", type);
 
+       /* The hardware needs special lowering for Gather4 with integer formats. */
+       if (opcode == TGSI_OPCODE_TG4) {
+               struct tgsi_shader_info *info = &ctx->shader->selector->info;
+               /* This will also work with non-constant indexing because of how
+                * glsl_to_tgsi works and we intent to preserve that behavior.
+                */
+               const unsigned src_idx = 2;
+               unsigned sampler = inst->Src[src_idx].Register.Index;
+
+               assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER);
+
+               if (info->sampler_type[sampler] == TGSI_RETURN_TYPE_SINT ||
+                   info->sampler_type[sampler] == TGSI_RETURN_TYPE_UINT) {
+                       /* Texture coordinates start after:
+                        *   {offset, bias, z-compare, derivatives}
+                        * Only the offset and z-compare can occur here.
+                        */
+                       si_lower_gather4_integer(ctx, emit_data, intr_name,
+                                                (int)has_offset + (int)is_shadow);
+                       return;
+               }
+       }
+
        emit_data->output[emit_data->chan] = lp_build_intrinsic(
                base->gallivm->builder, intr_name, emit_data->dst_type,
                emit_data->args, emit_data->arg_count,
@@ -4863,21 +5039,12 @@ static void si_llvm_emit_ddxy(
 {
        struct si_shader_context *ctx = si_shader_context(bld_base);
        struct gallivm_state *gallivm = bld_base->base.gallivm;
-       const struct tgsi_full_instruction *inst = emit_data->inst;
-       unsigned opcode = inst->Instruction.Opcode;
-       LLVMValueRef indices[2];
-       LLVMValueRef store_ptr, load_ptr0, load_ptr1;
-       LLVMValueRef tl, trbl, result[4];
-       LLVMValueRef tl_tid, trbl_tid;
-       unsigned swizzle[4];
-       unsigned c;
+       unsigned opcode = emit_data->info->opcode;
+       LLVMValueRef thread_id, tl, trbl, tl_tid, trbl_tid, val, args[2];
        int idx;
        unsigned mask;
 
-       indices[0] = bld_base->uint_bld.zero;
-       indices[1] = get_thread_id(ctx);
-       store_ptr = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                indices, 2, "");
+       thread_id = get_thread_id(ctx);
 
        if (opcode == TGSI_OPCODE_DDX_FINE)
                mask = TID_MASK_LEFT;
@@ -4886,64 +5053,46 @@ static void si_llvm_emit_ddxy(
        else
                mask = TID_MASK_TOP_LEFT;
 
-       tl_tid = LLVMBuildAnd(gallivm->builder, indices[1],
+       tl_tid = LLVMBuildAnd(gallivm->builder, thread_id,
                                lp_build_const_int32(gallivm, mask), "");
-       indices[1] = tl_tid;
-       load_ptr0 = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                indices, 2, "");
 
        /* for DDX we want to next X pixel, DDY next Y pixel. */
        idx = (opcode == TGSI_OPCODE_DDX || opcode == TGSI_OPCODE_DDX_FINE) ? 1 : 2;
-       trbl_tid = LLVMBuildAdd(gallivm->builder, indices[1],
+       trbl_tid = LLVMBuildAdd(gallivm->builder, tl_tid,
                                  lp_build_const_int32(gallivm, idx), "");
-       indices[1] = trbl_tid;
-       load_ptr1 = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                indices, 2, "");
 
-       for (c = 0; c < 4; ++c) {
-               unsigned i;
-               LLVMValueRef val;
-               LLVMValueRef args[2];
+       val = LLVMBuildBitCast(gallivm->builder, emit_data->args[0], ctx->i32, "");
 
-               swizzle[c] = tgsi_util_get_full_src_register_swizzle(&inst->Src[0], c);
-               for (i = 0; i < c; ++i) {
-                       if (swizzle[i] == swizzle[c]) {
-                               result[c] = result[i];
-                               break;
-                       }
-               }
-               if (i != c)
-                       continue;
-
-               val = LLVMBuildBitCast(gallivm->builder,
-                               lp_build_emit_fetch(bld_base, inst, 0, c),
-                                               ctx->i32, "");
-
-               if ((HAVE_LLVM >= 0x0309) && ctx->screen->b.family >= CHIP_TONGA) {
-
-                       args[0] = LLVMBuildMul(gallivm->builder, tl_tid,
-                                        lp_build_const_int32(gallivm, 4), "");
-                       args[1] = val;
-                       tl = lp_build_intrinsic(gallivm->builder,
+       if (ctx->screen->has_ds_bpermute) {
+               args[0] = LLVMBuildMul(gallivm->builder, tl_tid,
+                                      lp_build_const_int32(gallivm, 4), "");
+               args[1] = val;
+               tl = lp_build_intrinsic(gallivm->builder,
                                        "llvm.amdgcn.ds.bpermute", ctx->i32,
                                        args, 2, LLVMReadNoneAttribute);
 
-                       args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
-                                        lp_build_const_int32(gallivm, 4), "");
-                       trbl = lp_build_intrinsic(gallivm->builder,
-                                       "llvm.amdgcn.ds.bpermute", ctx->i32,
-                                       args, 2, LLVMReadNoneAttribute);
-               } else {
-                       LLVMBuildStore(gallivm->builder, val, store_ptr);
-                       tl = LLVMBuildLoad(gallivm->builder, load_ptr0, "");
-                       trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
-               }
-               tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-               trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
-               result[c] = LLVMBuildFSub(gallivm->builder, trbl, tl, "");
+               args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
+                                      lp_build_const_int32(gallivm, 4), "");
+               trbl = lp_build_intrinsic(gallivm->builder,
+                                         "llvm.amdgcn.ds.bpermute", ctx->i32,
+                                         args, 2, LLVMReadNoneAttribute);
+       } else {
+               LLVMValueRef store_ptr, load_ptr0, load_ptr1;
+
+               store_ptr = build_gep0(ctx, ctx->lds, thread_id);
+               load_ptr0 = build_gep0(ctx, ctx->lds, tl_tid);
+               load_ptr1 = build_gep0(ctx, ctx->lds, trbl_tid);
+
+               LLVMBuildStore(gallivm->builder, val, store_ptr);
+               tl = LLVMBuildLoad(gallivm->builder, load_ptr0, "");
+               trbl = LLVMBuildLoad(gallivm->builder, load_ptr1, "");
        }
 
-       emit_data->output[0] = lp_build_gather_values(gallivm, result, 4);
+       tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
+       trbl = LLVMBuildBitCast(gallivm->builder, trbl, ctx->f32, "");
+
+       emit_data->output[emit_data->chan] =
+               LLVMBuildFSub(gallivm->builder, trbl, tl, "");
 }
 
 /*
@@ -4957,65 +5106,14 @@ static LLVMValueRef si_llvm_emit_ddxy_interp(
 {
        struct si_shader_context *ctx = si_shader_context(bld_base);
        struct gallivm_state *gallivm = bld_base->base.gallivm;
-       LLVMValueRef indices[2];
-       LLVMValueRef store_ptr, load_ptr_x, load_ptr_y, load_ptr_ddx, load_ptr_ddy, temp, temp2;
-       LLVMValueRef tl, tr, bl, result[4];
-       unsigned c;
-
-       indices[0] = bld_base->uint_bld.zero;
-       indices[1] = get_thread_id(ctx);
-       store_ptr = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                indices, 2, "");
-
-       temp = LLVMBuildAnd(gallivm->builder, indices[1],
-                           lp_build_const_int32(gallivm, TID_MASK_LEFT), "");
-
-       temp2 = LLVMBuildAnd(gallivm->builder, indices[1],
-                            lp_build_const_int32(gallivm, TID_MASK_TOP), "");
-
-       indices[1] = temp;
-       load_ptr_x = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                 indices, 2, "");
-
-       indices[1] = temp2;
-       load_ptr_y = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                 indices, 2, "");
-
-       indices[1] = LLVMBuildAdd(gallivm->builder, temp,
-                                 lp_build_const_int32(gallivm, 1), "");
-       load_ptr_ddx = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                  indices, 2, "");
-
-       indices[1] = LLVMBuildAdd(gallivm->builder, temp2,
-                                 lp_build_const_int32(gallivm, 2), "");
-       load_ptr_ddy = LLVMBuildGEP(gallivm->builder, ctx->lds,
-                                  indices, 2, "");
-
-       for (c = 0; c < 2; ++c) {
-               LLVMValueRef store_val;
-               LLVMValueRef c_ll = lp_build_const_int32(gallivm, c);
-
-               store_val = LLVMBuildExtractElement(gallivm->builder,
-                                                   interp_ij, c_ll, "");
-               LLVMBuildStore(gallivm->builder,
-                              store_val,
-                              store_ptr);
-
-               tl = LLVMBuildLoad(gallivm->builder, load_ptr_x, "");
-               tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
-               tr = LLVMBuildLoad(gallivm->builder, load_ptr_ddx, "");
-               tr = LLVMBuildBitCast(gallivm->builder, tr, ctx->f32, "");
-
-               result[c] = LLVMBuildFSub(gallivm->builder, tr, tl, "");
-
-               tl = LLVMBuildLoad(gallivm->builder, load_ptr_y, "");
-               tl = LLVMBuildBitCast(gallivm->builder, tl, ctx->f32, "");
-
-               bl = LLVMBuildLoad(gallivm->builder, load_ptr_ddy, "");
-               bl = LLVMBuildBitCast(gallivm->builder, bl, ctx->f32, "");
+       LLVMValueRef result[4], a;
+       unsigned i;
 
-               result[c + 2] = LLVMBuildFSub(gallivm->builder, bl, tl, "");
+       for (i = 0; i < 2; i++) {
+               a = LLVMBuildExtractElement(gallivm->builder, interp_ij,
+                                           LLVMConstInt(ctx->i32, i, 0), "");
+               result[i] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_DDX, a);
+               result[2+i] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_DDY, a);
        }
 
        return lp_build_gather_values(gallivm, result, 4);
@@ -5144,7 +5242,7 @@ static void build_interp_intrinsic(const struct lp_build_tgsi_action *action,
        }
 
        intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant";
-       for (chan = 0; chan < 2; chan++) {
+       for (chan = 0; chan < 4; chan++) {
                LLVMValueRef args[4];
                LLVMValueRef llvm_chan;
                unsigned schan;
@@ -5616,6 +5714,7 @@ static void create_function(struct si_shader_context *ctx)
 
        case PIPE_SHADER_COMPUTE:
                params[SI_PARAM_GRID_SIZE] = v3i32;
+               params[SI_PARAM_BLOCK_SIZE] = v3i32;
                params[SI_PARAM_BLOCK_ID] = v3i32;
                last_sgpr = SI_PARAM_BLOCK_ID;
 
@@ -5652,7 +5751,12 @@ static void create_function(struct si_shader_context *ctx)
                               properties[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
                               properties[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH];
 
-               assert(max_work_group_size);
+               if (!max_work_group_size) {
+                       /* This is a variable group size compute shader,
+                        * compile it for the maximum possible group size.
+                        */
+                       max_work_group_size = SI_MAX_VARIABLE_THREADS_PER_BLOCK;
+               }
 
                radeon_llvm_add_attribute(ctx->radeon_bld.main_fn,
                                          "amdgpu-max-work-group-size",
@@ -5672,7 +5776,8 @@ static void create_function(struct si_shader_context *ctx)
                for (; i < num_params; ++i)
                        shader->info.num_input_vgprs += llvm_get_type_size(params[i]) / 4;
 
-       if (bld_base->info &&
+       if (!ctx->screen->has_ds_bpermute &&
+           bld_base->info &&
            (bld_base->info->opcode_count[TGSI_OPCODE_DDX] > 0 ||
             bld_base->info->opcode_count[TGSI_OPCODE_DDY] > 0 ||
             bld_base->info->opcode_count[TGSI_OPCODE_DDX_FINE] > 0 ||
@@ -5691,141 +5796,6 @@ static void create_function(struct si_shader_context *ctx)
                declare_tess_lds(ctx);
 }
 
-static void preload_constants(struct si_shader_context *ctx)
-{
-       struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
-       struct gallivm_state *gallivm = bld_base->base.gallivm;
-       const struct tgsi_shader_info *info = bld_base->info;
-       unsigned buf;
-       LLVMValueRef ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_CONST_BUFFERS);
-
-       for (buf = 0; buf < SI_NUM_CONST_BUFFERS; buf++) {
-               unsigned i, num_const = info->const_file_max[buf] + 1;
-
-               if (num_const == 0)
-                       continue;
-
-               /* Allocate space for the constant values */
-               ctx->constants[buf] = CALLOC(num_const * 4, sizeof(LLVMValueRef));
-
-               /* Load the resource descriptor */
-               ctx->const_buffers[buf] =
-                       build_indexed_load_const(ctx, ptr, lp_build_const_int32(gallivm, buf));
-
-               /* Load the constants, we rely on the code sinking to do the rest */
-               for (i = 0; i < num_const * 4; ++i) {
-                       ctx->constants[buf][i] =
-                               buffer_load_const(ctx,
-                                       ctx->const_buffers[buf],
-                                       lp_build_const_int32(gallivm, i * 4));
-               }
-       }
-}
-
-static void preload_shader_buffers(struct si_shader_context *ctx)
-{
-       struct gallivm_state *gallivm = &ctx->radeon_bld.gallivm;
-       LLVMValueRef ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_SHADER_BUFFERS);
-       int buf, maxbuf;
-
-       maxbuf = MIN2(ctx->shader->selector->info.file_max[TGSI_FILE_BUFFER],
-                     SI_NUM_SHADER_BUFFERS - 1);
-       for (buf = 0; buf <= maxbuf; ++buf) {
-               ctx->shader_buffers[buf] =
-                       build_indexed_load_const(
-                               ctx, ptr, lp_build_const_int32(gallivm, buf));
-       }
-}
-
-static void preload_samplers(struct si_shader_context *ctx)
-{
-       struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
-       struct gallivm_state *gallivm = bld_base->base.gallivm;
-       const struct tgsi_shader_info *info = bld_base->info;
-       unsigned i, num_samplers = info->file_max[TGSI_FILE_SAMPLER] + 1;
-       LLVMValueRef offset;
-
-       if (num_samplers == 0)
-               return;
-
-       /* Load the resources and samplers, we rely on the code sinking to do the rest */
-       for (i = 0; i < num_samplers; ++i) {
-               /* Resource */
-               offset = lp_build_const_int32(gallivm, i);
-               ctx->sampler_views[i] =
-                       get_sampler_desc(ctx, offset, DESC_IMAGE);
-
-               /* FMASK resource */
-               if (info->is_msaa_sampler[i])
-                       ctx->fmasks[i] =
-                               get_sampler_desc(ctx, offset, DESC_FMASK);
-               else {
-                       ctx->sampler_states[i] =
-                               get_sampler_desc(ctx, offset, DESC_SAMPLER);
-                       ctx->sampler_states[i] =
-                               sici_fix_sampler_aniso(ctx, ctx->sampler_views[i],
-                                                      ctx->sampler_states[i]);
-               }
-       }
-}
-
-static void preload_images(struct si_shader_context *ctx)
-{
-       struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
-       struct tgsi_shader_info *info = &ctx->shader->selector->info;
-       struct gallivm_state *gallivm = bld_base->base.gallivm;
-       unsigned num_images = bld_base->info->file_max[TGSI_FILE_IMAGE] + 1;
-       LLVMValueRef res_ptr;
-       unsigned i;
-
-       if (num_images == 0)
-               return;
-
-       res_ptr = LLVMGetParam(ctx->radeon_bld.main_fn, SI_PARAM_IMAGES);
-
-       for (i = 0; i < num_images; ++i) {
-               /* Rely on LLVM to shrink the load for buffer resources. */
-               LLVMValueRef rsrc =
-                       build_indexed_load_const(ctx, res_ptr,
-                                                lp_build_const_int32(gallivm, i));
-
-               if (info->images_writemask & (1 << i) &&
-                   !(info->images_buffers & (1 << i)))
-                       rsrc = force_dcc_off(ctx, rsrc);
-
-               ctx->images[i] = rsrc;
-       }
-}
-
-static void preload_streamout_buffers(struct si_shader_context *ctx)
-{
-       struct lp_build_tgsi_context *bld_base = &ctx->radeon_bld.soa.bld_base;
-       struct gallivm_state *gallivm = bld_base->base.gallivm;
-       unsigned i;
-
-       /* Streamout can only be used if the shader is compiled as VS. */
-       if (!ctx->shader->selector->so.num_outputs ||
-           (ctx->type == PIPE_SHADER_VERTEX &&
-            (ctx->shader->key.vs.as_es ||
-             ctx->shader->key.vs.as_ls)) ||
-           (ctx->type == PIPE_SHADER_TESS_EVAL &&
-            ctx->shader->key.tes.as_es))
-               return;
-
-       LLVMValueRef buf_ptr = LLVMGetParam(ctx->radeon_bld.main_fn,
-                                           SI_PARAM_RW_BUFFERS);
-
-       /* Load the resources, we rely on the code sinking to do the rest */
-       for (i = 0; i < 4; ++i) {
-               if (ctx->shader->selector->so.stride[i]) {
-                       LLVMValueRef offset = lp_build_const_int32(gallivm,
-                                                                  SI_VS_STREAMOUT_BUF0 + i);
-
-                       ctx->so_buffers[i] = build_indexed_load_const(ctx, buf_ptr, offset);
-               }
-       }
-}
-
 /**
  * Load ESGS and GSVS ring buffer resource descriptors and save the variables
  * for later use.
@@ -6370,7 +6340,6 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen,
 
        create_meta_data(ctx);
        create_function(ctx);
-       preload_streamout_buffers(ctx);
        preload_ring_buffers(ctx);
 
        args[0] = ctx->gsvs_ring[0];
@@ -6416,7 +6385,9 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen,
            r600_can_dump_shader(&sscreen->b, PIPE_SHADER_GEOMETRY))
                LLVMDumpModule(bld_base->base.gallivm->module);
 
-       radeon_llvm_finalize_module(&ctx->radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx->radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_GEOMETRY));
 
        r = si_compile_llvm(sscreen, &ctx->shader->binary,
                            &ctx->shader->config, ctx->tm,
@@ -6668,11 +6639,6 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
 
        create_meta_data(&ctx);
        create_function(&ctx);
-       preload_constants(&ctx);
-       preload_shader_buffers(&ctx);
-       preload_samplers(&ctx);
-       preload_images(&ctx);
-       preload_streamout_buffers(&ctx);
        preload_ring_buffers(&ctx);
 
        if (ctx.is_monolithic && sel->type == PIPE_SHADER_FRAGMENT &&
@@ -6705,7 +6671,9 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
            r600_can_dump_shader(&sscreen->b, ctx.type))
                LLVMDumpModule(mod);
 
-       radeon_llvm_finalize_module(&ctx.radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx.radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, ctx.type));
 
        r = si_compile_llvm(sscreen, &shader->binary, &shader->config, tm,
                            mod, debug, ctx.type, "TGSI shader");
@@ -6725,11 +6693,16 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
                unsigned max_vgprs = 256;
                unsigned max_sgprs = sscreen->b.chip_class >= VI ? 800 : 512;
                unsigned max_sgprs_per_wave = 128;
-               unsigned min_waves_per_cu =
-                       DIV_ROUND_UP(props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] *
-                                    props[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
-                                    props[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH],
-                                    wave_size);
+               unsigned max_block_threads;
+
+               if (props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH])
+                       max_block_threads = props[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] *
+                                           props[TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT] *
+                                           props[TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH];
+               else
+                       max_block_threads = SI_MAX_VARIABLE_THREADS_PER_BLOCK;
+
+               unsigned min_waves_per_cu = DIV_ROUND_UP(max_block_threads, wave_size);
                unsigned min_waves_per_simd = DIV_ROUND_UP(min_waves_per_cu, 4);
 
                max_vgprs = max_vgprs / min_waves_per_simd;
@@ -6809,8 +6782,6 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
        }
 
 out:
-       for (int i = 0; i < SI_NUM_CONST_BUFFERS; i++)
-               FREE(ctx.constants[i]);
        return r;
 }
 
@@ -6968,7 +6939,9 @@ static bool si_compile_vs_prolog(struct si_screen *sscreen,
 
        /* Compile. */
        si_llvm_build_ret(&ctx, ret);
-       radeon_llvm_finalize_module(&ctx.radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx.radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
 
        if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
                            gallivm->module, debug, ctx.type,
@@ -7040,7 +7013,9 @@ static bool si_compile_vs_epilog(struct si_screen *sscreen,
 
        /* Compile. */
        LLVMBuildRetVoid(gallivm->builder);
-       radeon_llvm_finalize_module(&ctx.radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx.radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
 
        if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
                            gallivm->module, debug, ctx.type,
@@ -7193,7 +7168,9 @@ static bool si_compile_tcs_epilog(struct si_screen *sscreen,
 
        /* Compile. */
        LLVMBuildRetVoid(gallivm->builder);
-       radeon_llvm_finalize_module(&ctx.radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx.radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_TESS_CTRL));
 
        if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
                            gallivm->module, debug, ctx.type,
@@ -7353,54 +7330,6 @@ static bool si_compile_ps_prolog(struct si_screen *sscreen,
                }
        }
 
-       /* Interpolate colors. */
-       for (i = 0; i < 2; i++) {
-               unsigned writemask = (key->ps_prolog.colors_read >> (i * 4)) & 0xf;
-               unsigned face_vgpr = key->ps_prolog.num_input_sgprs +
-                                    key->ps_prolog.face_vgpr_index;
-               LLVMValueRef interp[2], color[4];
-               LLVMValueRef interp_ij = NULL, prim_mask = NULL, face = NULL;
-
-               if (!writemask)
-                       continue;
-
-               /* If the interpolation qualifier is not CONSTANT (-1). */
-               if (key->ps_prolog.color_interp_vgpr_index[i] != -1) {
-                       unsigned interp_vgpr = key->ps_prolog.num_input_sgprs +
-                                              key->ps_prolog.color_interp_vgpr_index[i];
-
-                       /* Get the (i,j) updated by bc_optimize handling. */
-                       interp[0] = LLVMBuildExtractValue(gallivm->builder, ret,
-                                                         interp_vgpr, "");
-                       interp[1] = LLVMBuildExtractValue(gallivm->builder, ret,
-                                                         interp_vgpr + 1, "");
-                       interp_ij = lp_build_gather_values(gallivm, interp, 2);
-                       interp_ij = LLVMBuildBitCast(gallivm->builder, interp_ij,
-                                                    ctx.v2i32, "");
-               }
-
-               /* Use the absolute location of the input. */
-               prim_mask = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
-
-               if (key->ps_prolog.states.color_two_side) {
-                       face = LLVMGetParam(func, face_vgpr);
-                       face = LLVMBuildBitCast(gallivm->builder, face, ctx.i32, "");
-               }
-
-               interp_fs_input(&ctx,
-                               key->ps_prolog.color_attr_index[i],
-                               TGSI_SEMANTIC_COLOR, i,
-                               key->ps_prolog.num_interp_inputs,
-                               key->ps_prolog.colors_read, interp_ij,
-                               prim_mask, face, color);
-
-               while (writemask) {
-                       unsigned chan = u_bit_scan(&writemask);
-                       ret = LLVMBuildInsertValue(gallivm->builder, ret, color[chan],
-                                                  num_params++, "");
-               }
-       }
-
        /* Force per-sample interpolation. */
        if (key->ps_prolog.states.force_persp_sample_interp) {
                unsigned i, base = key->ps_prolog.num_input_sgprs;
@@ -7469,6 +7398,54 @@ static bool si_compile_ps_prolog(struct si_screen *sscreen,
                                                   linear_center[i], base + 10 + i, "");
        }
 
+       /* Interpolate colors. */
+       for (i = 0; i < 2; i++) {
+               unsigned writemask = (key->ps_prolog.colors_read >> (i * 4)) & 0xf;
+               unsigned face_vgpr = key->ps_prolog.num_input_sgprs +
+                                    key->ps_prolog.face_vgpr_index;
+               LLVMValueRef interp[2], color[4];
+               LLVMValueRef interp_ij = NULL, prim_mask = NULL, face = NULL;
+
+               if (!writemask)
+                       continue;
+
+               /* If the interpolation qualifier is not CONSTANT (-1). */
+               if (key->ps_prolog.color_interp_vgpr_index[i] != -1) {
+                       unsigned interp_vgpr = key->ps_prolog.num_input_sgprs +
+                                              key->ps_prolog.color_interp_vgpr_index[i];
+
+                       /* Get the (i,j) updated by bc_optimize handling. */
+                       interp[0] = LLVMBuildExtractValue(gallivm->builder, ret,
+                                                         interp_vgpr, "");
+                       interp[1] = LLVMBuildExtractValue(gallivm->builder, ret,
+                                                         interp_vgpr + 1, "");
+                       interp_ij = lp_build_gather_values(gallivm, interp, 2);
+                       interp_ij = LLVMBuildBitCast(gallivm->builder, interp_ij,
+                                                    ctx.v2i32, "");
+               }
+
+               /* Use the absolute location of the input. */
+               prim_mask = LLVMGetParam(func, SI_PS_NUM_USER_SGPR);
+
+               if (key->ps_prolog.states.color_two_side) {
+                       face = LLVMGetParam(func, face_vgpr);
+                       face = LLVMBuildBitCast(gallivm->builder, face, ctx.i32, "");
+               }
+
+               interp_fs_input(&ctx,
+                               key->ps_prolog.color_attr_index[i],
+                               TGSI_SEMANTIC_COLOR, i,
+                               key->ps_prolog.num_interp_inputs,
+                               key->ps_prolog.colors_read, interp_ij,
+                               prim_mask, face, color);
+
+               while (writemask) {
+                       unsigned chan = u_bit_scan(&writemask);
+                       ret = LLVMBuildInsertValue(gallivm->builder, ret, color[chan],
+                                                  num_params++, "");
+               }
+       }
+
        /* Tell LLVM to insert WQM instruction sequence when needed. */
        if (key->ps_prolog.wqm) {
                LLVMAddTargetDependentFunctionAttr(func,
@@ -7477,7 +7454,9 @@ static bool si_compile_ps_prolog(struct si_screen *sscreen,
 
        /* Compile. */
        si_llvm_build_ret(&ctx, ret);
-       radeon_llvm_finalize_module(&ctx.radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx.radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
 
        if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
                            gallivm->module, debug, ctx.type,
@@ -7597,7 +7576,9 @@ static bool si_compile_ps_epilog(struct si_screen *sscreen,
 
        /* Compile. */
        LLVMBuildRetVoid(gallivm->builder);
-       radeon_llvm_finalize_module(&ctx.radeon_bld);
+       radeon_llvm_finalize_module(
+               &ctx.radeon_bld,
+               r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
 
        if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
                            gallivm->module, debug, ctx.type,