<div dir="ltr"><div><div>For the series:<br><br></div>Acked-by: Marek Olšák <<a href="mailto:marek.olsak@amd.com">marek.olsak@amd.com</a>><br><br></div><div>Marek<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 11, 2018 at 7:13 AM, Nicolai Hähnle <span dir="ltr"><<a href="mailto:nhaehnle@gmail.com" target="_blank">nhaehnle@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
<br>
Requires LLVM trunk r329166.<br>
---<br>
 src/amd/common/ac_llvm_build.c | 189 ++++++++++++++++++++++++++++++<wbr>+++++------<br>
 1 file changed, 165 insertions(+), 24 deletions(-)<br>
<br>
diff --git a/src/amd/common/ac_llvm_<wbr>build.c b/src/amd/common/ac_llvm_<wbr>build.c<br>
index b5561533437..15768d1d26d 100644<br>
--- a/src/amd/common/ac_llvm_<wbr>build.c<br>
+++ b/src/amd/common/ac_llvm_<wbr>build.c<br>
@@ -1462,39 +1462,47 @@ static unsigned ac_num_derivs(enum ac_image_dim dim)<br>
                return 4;<br>
        case ac_image_3d:<br>
                return 6;<br>
        case ac_image_2dmsaa:<br>
        case ac_image_2darraymsaa:<br>
        default:<br>
                unreachable("derivatives not supported");<br>
        }<br>
 }<br>
<br>
-LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx,<br>
-                                  struct ac_image_args *a)<br>
+static const char *get_atomic_name(enum ac_atomic_op op)<br>
+{<br>
+       switch (op) {<br>
+       case ac_atomic_swap: return "swap";<br>
+       case ac_atomic_add: return "add";<br>
+       case ac_atomic_sub: return "sub";<br>
+       case ac_atomic_smin: return "smin";<br>
+       case ac_atomic_umin: return "umin";<br>
+       case ac_atomic_smax: return "smax";<br>
+       case ac_atomic_umax: return "umax";<br>
+       case ac_atomic_and: return "and";<br>
+       case ac_atomic_or: return "or";<br>
+       case ac_atomic_xor: return "xor";<br>
+       }<br>
+       unreachable("bad atomic op");<br>
+}<br>
+<br>
+/* LLVM 6 and older */<br>
+static LLVMValueRef ac_build_image_opcode_llvm6(<wbr>struct ac_llvm_context *ctx,<br>
+                                               struct ac_image_args *a)<br>
 {<br>
        LLVMValueRef args[16];<br>
        LLVMTypeRef retty = ctx->v4f32;<br>
        const char *name = NULL;<br>
        const char *atomic_subop = "";<br>
        char intr_name[128], coords_type[64];<br>
<br>
-       assert(!a->lod || a->lod == ctx->i32_0 || a->lod == ctx->f32_0 ||<br>
-              !a->level_zero);<br>
-       assert((a->opcode != ac_image_get_resinfo && a->opcode != ac_image_load_mip &&<br>
-               a->opcode != ac_image_store_mip) ||<br>
-              a->lod);<br>
-       assert((a->bias ? 1 : 0) +<br>
-              (a->lod ? 1 : 0) +<br>
-              (a->level_zero ? 1 : 0) +<br>
-              (a->derivs[0] ? 1 : 0) <= 1);<br>
-<br>
        bool sample = a->opcode == ac_image_sample ||<br>
                      a->opcode == ac_image_gather4 ||<br>
                      a->opcode == ac_image_get_lod;<br>
        bool atomic = a->opcode == ac_image_atomic ||<br>
                      a->opcode == ac_image_atomic_cmpswap;<br>
        bool da = a->dim == ac_image_cube ||<br>
                  a->dim == ac_image_1darray ||<br>
                  a->dim == ac_image_2darray ||<br>
                  a->dim == ac_image_2darraymsaa;<br>
        if (a->opcode == ac_image_get_lod)<br>
@@ -1578,32 +1586,21 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx,<br>
                name = "llvm.amdgcn.image.store.mip";<br>
                retty = ctx->voidt;<br>
                break;<br>
        case ac_image_atomic:<br>
        case ac_image_atomic_cmpswap:<br>
                name = "llvm.amdgcn.image.atomic.";<br>
                retty = ctx->i32;<br>
                if (a->opcode == ac_image_atomic_cmpswap) {<br>
                        atomic_subop = "cmpswap";<br>
                } else {<br>
-                       switch (a->atomic) {<br>
-                       case ac_atomic_swap: atomic_subop = "swap"; break;<br>
-                       case ac_atomic_add: atomic_subop = "add"; break;<br>
-                       case ac_atomic_sub: atomic_subop = "sub"; break;<br>
-                       case ac_atomic_smin: atomic_subop = "smin"; break;<br>
-                       case ac_atomic_umin: atomic_subop = "umin"; break;<br>
-                       case ac_atomic_smax: atomic_subop = "smax"; break;<br>
-                       case ac_atomic_umax: atomic_subop = "umax"; break;<br>
-                       case ac_atomic_and: atomic_subop = "and"; break;<br>
-                       case ac_atomic_or: atomic_subop = "or"; break;<br>
-                       case ac_atomic_xor: atomic_subop = "xor"; break;<br>
-                       }<br>
+                       atomic_subop = get_atomic_name(a->atomic);<br>
                }<br>
                break;<br>
        case ac_image_get_lod:<br>
                name = "llvm.amdgcn.image.getlod";<br>
                break;<br>
        case ac_image_get_resinfo:<br>
                name = "llvm.amdgcn.image.getresinfo"<wbr>;<br>
                break;<br>
        default:<br>
                unreachable("invalid image opcode");<br>
@@ -1633,20 +1630,164 @@ LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx,<br>
        LLVMValueRef result =<br>
                ac_build_intrinsic(ctx, intr_name, retty, args, num_args,<br>
                                   a->attributes);<br>
        if (!sample && retty == ctx->v4f32) {<br>
                result = LLVMBuildBitCast(ctx->builder, result,<br>
                                          ctx->v4i32, "");<br>
        }<br>
        return result;<br>
 }<br>
<br>
+LLVMValueRef ac_build_image_opcode(struct ac_llvm_context *ctx,<br>
+                                  struct ac_image_args *a)<br>
+{<br>
+       const char *overload[3] = { "", "", "" };<br>
+       unsigned num_overloads = 0;<br>
+       LLVMValueRef args[18];<br>
+       unsigned num_args = 0;<br>
+<br>
+       assert(!a->lod || a->lod == ctx->i32_0 || a->lod == ctx->f32_0 ||<br>
+              !a->level_zero);<br>
+       assert((a->opcode != ac_image_get_resinfo && a->opcode != ac_image_load_mip &&<br>
+               a->opcode != ac_image_store_mip) ||<br>
+              a->lod);<br>
+       assert(a->opcode == ac_image_sample || a->opcode == ac_image_gather4 ||<br>
+              (!a->compare && !a->offset));<br>
+       assert((a->opcode == ac_image_sample || a->opcode == ac_image_gather4 ||<br>
+               a->opcode == ac_image_get_lod) ||<br>
+              !a->bias);<br>
+       assert((a->bias ? 1 : 0) +<br>
+              (a->lod ? 1 : 0) +<br>
+              (a->level_zero ? 1 : 0) +<br>
+              (a->derivs[0] ? 1 : 0) <= 1);<br>
+<br>
+       if (HAVE_LLVM < 0x0700)<br>
+               return ac_build_image_opcode_llvm6(<wbr>ctx, a);<br>
+<br>
+       bool sample = a->opcode == ac_image_sample ||<br>
+                     a->opcode == ac_image_gather4 ||<br>
+                     a->opcode == ac_image_get_lod;<br>
+       bool atomic = a->opcode == ac_image_atomic ||<br>
+                     a->opcode == ac_image_atomic_cmpswap;<br>
+       LLVMTypeRef coord_type = sample ? ctx->f32 : ctx->i32;<br>
+<br>
+       if (atomic || a->opcode == ac_image_store || a->opcode == ac_image_store_mip) {<br>
+               args[num_args++] = a->data[0];<br>
+               if (a->opcode == ac_image_atomic_cmpswap)<br>
+                       args[num_args++] = a->data[1];<br>
+       }<br>
+<br>
+       if (!atomic)<br>
+               args[num_args++] = LLVMConstInt(ctx->i32, a->dmask, false);<br>
+<br>
+       if (a->offset)<br>
+               args[num_args++] = ac_to_integer(ctx, a->offset);<br>
+       if (a->bias) {<br>
+               args[num_args++] = ac_to_float(ctx, a->bias);<br>
+               overload[num_overloads++] = ".f32";<br>
+       }<br>
+       if (a->compare)<br>
+               args[num_args++] = ac_to_float(ctx, a->compare);<br>
+       if (a->derivs[0]) {<br>
+               unsigned count = ac_num_derivs(a->dim);<br>
+               for (unsigned i = 0; i < count; ++i)<br>
+                       args[num_args++] = ac_to_float(ctx, a->derivs[i]);<br>
+               overload[num_overloads++] = ".f32";<br>
+       }<br>
+       unsigned num_coords =<br>
+               a->opcode != ac_image_get_resinfo ? ac_num_coords(a->dim) : 0;<br>
+       for (unsigned i = 0; i < num_coords; ++i)<br>
+               args[num_args++] = LLVMBuildBitCast(ctx->builder, a->coords[i], coord_type, "");<br>
+       if (a->lod)<br>
+               args[num_args++] = LLVMBuildBitCast(ctx->builder, a->lod, coord_type, "");<br>
+       overload[num_overloads++] = sample ? ".f32" : ".i32";<br>
+<br>
+       args[num_args++] = a->resource;<br>
+       if (sample) {<br>
+               args[num_args++] = a->sampler;<br>
+               args[num_args++] = LLVMConstInt(ctx->i1, a->unorm, false);<br>
+       }<br>
+<br>
+       args[num_args++] = ctx->i32_0; /* texfailctrl */<br>
+       args[num_args++] = LLVMConstInt(ctx->i32, a->cache_policy, false);<br>
+<br>
+       const char *name;<br>
+       const char *atomic_subop = "";<br>
+       switch (a->opcode) {<br>
+       case ac_image_sample: name = "sample"; break;<br>
+       case ac_image_gather4: name = "gather4"; break;<br>
+       case ac_image_load: name = "load"; break;<br>
+       case ac_image_load_mip: name = "load.mip"; break;<br>
+       case ac_image_store: name = "store"; break;<br>
+       case ac_image_store_mip: name = "store.mip"; break;<br>
+       case ac_image_atomic:<br>
+               name = "atomic.";<br>
+               atomic_subop = get_atomic_name(a->atomic);<br>
+               break;<br>
+       case ac_image_atomic_cmpswap:<br>
+               name = "atomic.";<br>
+               atomic_subop = "cmpswap";<br>
+               break;<br>
+       case ac_image_get_lod: name = "getlod"; break;<br>
+       case ac_image_get_resinfo: name = "getresinfo"; break;<br>
+       default: unreachable("invalid image opcode");<br>
+       }<br>
+<br>
+       const char *dimname;<br>
+       switch (a->dim) {<br>
+       case ac_image_1d: dimname = "1d"; break;<br>
+       case ac_image_2d: dimname = "2d"; break;<br>
+       case ac_image_3d: dimname = "3d"; break;<br>
+       case ac_image_cube: dimname = "cube"; break;<br>
+       case ac_image_1darray: dimname = "1darray"; break;<br>
+       case ac_image_2darray: dimname = "2darray"; break;<br>
+       case ac_image_2dmsaa: dimname = "2dmsaa"; break;<br>
+       case ac_image_2darraymsaa: dimname = "2darraymsaa"; break;<br>
+       default: unreachable("invalid dim");<br>
+       }<br>
+<br>
+       bool lod_suffix =<br>
+               a->lod && (a->opcode == ac_image_sample || a->opcode == ac_image_gather4);<br>
+       char intr_name[96];<br>
+       snprintf(intr_name, sizeof(intr_name),<br>
+                "llvm.amdgcn.image.%s%s" /* base name */<br>
+                "%s%s%s" /* sample/gather modifiers */<br>
+                ".%s.%s%s%s%s", /* dimension and type overloads */<br>
+                name, atomic_subop,<br>
+                a->compare ? ".c" : "",<br>
+                a->bias ? ".b" :<br>
+                lod_suffix ? ".l" :<br>
+                a->derivs[0] ? ".d" :<br>
+                a->level_zero ? ".lz" : "",<br>
+                a->offset ? ".o" : "",<br>
+                dimname,<br>
+                atomic ? "i32" : "v4f32",<br>
+                overload[0], overload[1], overload[2]);<br>
+<br>
+       LLVMTypeRef retty;<br>
+       if (atomic)<br>
+               retty = ctx->i32;<br>
+       else if (a->opcode == ac_image_store || a->opcode == ac_image_store_mip)<br>
+               retty = ctx->voidt;<br>
+       else<br>
+               retty = ctx->v4f32;<br>
+<br>
+       LLVMValueRef result =<br>
+               ac_build_intrinsic(ctx, intr_name, retty, args, num_args,<br>
+                                  a->attributes);<br>
+       if (!sample && retty == ctx->v4f32) {<br>
+               result = LLVMBuildBitCast(ctx->builder, result,<br>
+                                         ctx->v4i32, "");<br>
+       }<br>
+       return result;<br>
+}<br>
+<br>
 LLVMValueRef ac_build_cvt_pkrtz_f16(struct ac_llvm_context *ctx,<br>
                                    LLVMValueRef args[2])<br>
 {<br>
        if (HAVE_LLVM >= 0x0500) {<br>
                LLVMTypeRef v2f16 =<br>
                        LLVMVectorType(<wbr>LLVMHalfTypeInContext(ctx-><wbr>context), 2);<br>
                LLVMValueRef res =<br>
                        ac_build_intrinsic(ctx, "llvm.amdgcn.cvt.pkrtz",<br>
                                           v2f16, args, 2,<br>
                                           AC_FUNC_ATTR_READNONE);<br>
<span class="HOEnZb"><font color="#888888">-- <br>
2.14.1<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div>