gallivm: Help for combined extraction and broadcasting.
authorJosé Fonseca <jfonseca@vmware.com>
Fri, 8 Oct 2010 18:48:16 +0000 (19:48 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Fri, 8 Oct 2010 18:48:16 +0000 (19:48 +0100)
Doesn't change generated code quality, but saves some typing.

src/gallium/auxiliary/gallivm/lp_bld_sample.c
src/gallium/auxiliary/gallivm/lp_bld_swizzle.c
src/gallium/auxiliary/gallivm/lp_bld_swizzle.h

index 6a684a9a0bf181c8fb02a17efded93c37ab2f4d8..7a64392d3c19d6b2c17abc1a840d4f5896597fc1 100644 (file)
@@ -639,7 +639,6 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld,
    const unsigned dims = bld->dims;
    LLVMValueRef ilevel_vec;
    LLVMValueRef size_vec;
-   LLVMValueRef width, height, depth;
    LLVMTypeRef i32t = LLVMInt32Type();
 
    ilevel_vec = lp_build_broadcast_scalar(&bld->int_size_bld, ilevel);
@@ -649,18 +648,19 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld,
     */
    size_vec = lp_build_minify(&bld->int_size_bld, bld->int_size, ilevel_vec);
 
-   if (dims <= 1) {
-      width = size_vec;
-   }
-   else {
-      width = LLVMBuildExtractElement(bld->builder, size_vec,
-                                      LLVMConstInt(i32t, 0, 0), "");
-   }
-   *out_width_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, width);
+   *out_width_vec = lp_build_extract_broadcast(bld->builder,
+                                               bld->int_size_type,
+                                               bld->int_coord_type,
+                                               size_vec,
+                                               LLVMConstInt(i32t, 0, 0));
    if (dims >= 2) {
-      height = LLVMBuildExtractElement(bld->builder, size_vec,
-                                       LLVMConstInt(i32t, 1, 0), "");
-      *out_height_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, height);
+
+      *out_height_vec = lp_build_extract_broadcast(bld->builder,
+                                                   bld->int_size_type,
+                                                   bld->int_coord_type,
+                                                   size_vec,
+                                                   LLVMConstInt(i32t, 1, 0));
+
       *row_stride_vec = lp_build_get_level_stride_vec(bld,
                                                       bld->row_stride_array,
                                                       ilevel);
@@ -669,9 +669,11 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld,
                                                          bld->img_stride_array,
                                                          ilevel);
          if (dims == 3) {
-            depth = LLVMBuildExtractElement(bld->builder, size_vec,
-                                            LLVMConstInt(i32t, 2, 0), "");
-            *out_depth_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, depth);
+            *out_depth_vec = lp_build_extract_broadcast(bld->builder,
+                                                        bld->int_size_type,
+                                                        bld->int_coord_type,
+                                                        size_vec,
+                                                        LLVMConstInt(i32t, 2, 0));
          }
       }
    }
index 2e9e8386de007de103b92aa7d227ab056dcd991e..4685a90e41818a0e7be2f8caa3554a175f8099ef 100644 (file)
@@ -100,6 +100,83 @@ lp_build_broadcast_scalar(struct lp_build_context *bld,
 }
 
 
+/**
+ * Combined extract and broadcast (or a mere shuffle when the two types match)
+ */
+LLVMValueRef
+lp_build_extract_broadcast(LLVMBuilderRef builder,
+                           struct lp_type src_type,
+                           struct lp_type dst_type,
+                           LLVMValueRef vector,
+                           LLVMValueRef index)
+{
+   LLVMTypeRef i32t = LLVMInt32Type();
+   LLVMValueRef res;
+
+   assert(src_type.floating == dst_type.floating);
+   assert(src_type.width    == dst_type.width);
+
+   assert(lp_check_value(src_type, vector));
+   assert(LLVMTypeOf(index) == i32t);
+
+   if (src_type.length == 1) {
+      if (dst_type.length == 1) {
+         /*
+          * Trivial scalar -> scalar.
+          */
+
+         res = vector;
+      }
+      else {
+         /*
+          * Broadcast scalar -> vector.
+          */
+
+         res = lp_build_broadcast(builder,
+                                  lp_build_vec_type(dst_type),
+                                  vector);
+      }
+   }
+   else {
+      if (dst_type.length == src_type.length) {
+         /*
+          * Special shuffle of the same size.
+          */
+
+         LLVMValueRef shuffle;
+         shuffle = lp_build_broadcast(builder,
+                                      LLVMVectorType(i32t, dst_type.length),
+                                      index);
+         res = LLVMBuildShuffleVector(builder, vector,
+                                      LLVMGetUndef(lp_build_vec_type(dst_type)),
+                                      shuffle, "");
+      }
+      else {
+         LLVMValueRef scalar;
+         scalar = LLVMBuildExtractElement(builder, vector, index, "");
+         if (dst_type.length == 1) {
+            /*
+             * Trivial extract scalar from vector.
+             */
+
+            res = scalar;
+         }
+         else {
+            /*
+             * General case of different sized vectors.
+             */
+
+            res = lp_build_broadcast(builder,
+                                     lp_build_vec_type(dst_type),
+                                     vector);
+         }
+      }
+   }
+
+   return res;
+}
+
+
 /**
  * Swizzle one channel into all other three channels.
  */
index f9b6a5e7258f5aa9b044a3199526dc0192a39488..fdea8442aef38eeb9cc28ee2791fcd3864e34b50 100644 (file)
@@ -55,6 +55,14 @@ lp_build_broadcast_scalar(struct lp_build_context *bld,
                           LLVMValueRef scalar);
 
 
+LLVMValueRef
+lp_build_extract_broadcast(LLVMBuilderRef builder,
+                           struct lp_type src_type,
+                           struct lp_type dst_type,
+                           LLVMValueRef vector,
+                           LLVMValueRef index);
+
+
 /**
  * Broadcast one channel of a vector composed of arrays of XYZW structures into
  * all four channel.