cso: move cso hashes to a more table driven scheme
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_conv.c
index 6967dd26225a5dcb2750a190f1f80ccc6015f7de..c261d761161c2cea1bfeb99dc2d91d158b958839 100644 (file)
  * return { i32, i32, i32, i32 } where each value is in [0, 2^dst_width-1].
  */
 LLVMValueRef
-lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
+lp_build_clamped_float_to_unsigned_norm(struct gallivm_state *gallivm,
                                         struct lp_type src_type,
                                         unsigned dst_width,
                                         LLVMValueRef src)
 {
-   LLVMTypeRef int_vec_type = lp_build_int_vec_type(src_type);
+   LLVMBuilderRef builder = gallivm->builder;
+   LLVMTypeRef int_vec_type = lp_build_int_vec_type(gallivm, src_type);
    LLVMValueRef res;
    unsigned mantissa;
 
@@ -122,10 +123,11 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
       scale = (double)mask/ubound;
       bias = (double)(1ULL << (mantissa - dst_width));
 
-      res = LLVMBuildFMul(builder, src, lp_build_const_vec(src_type, scale), "");
-      res = LLVMBuildFAdd(builder, res, lp_build_const_vec(src_type, bias), "");
+      res = LLVMBuildFMul(builder, src, lp_build_const_vec(gallivm, src_type, scale), "");
+      res = LLVMBuildFAdd(builder, res, lp_build_const_vec(gallivm, src_type, bias), "");
       res = LLVMBuildBitCast(builder, res, int_vec_type, "");
-      res = LLVMBuildAnd(builder, res, lp_build_const_int_vec(src_type, mask), "");
+      res = LLVMBuildAnd(builder, res,
+                         lp_build_const_int_vec(gallivm, src_type, mask), "");
    }
    else if (dst_width == (mantissa + 1)) {
       /*
@@ -138,7 +140,8 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
 
       scale = (double)((1ULL << dst_width) - 1);
 
-      res = LLVMBuildFMul(builder, src, lp_build_const_vec(src_type, scale), "");
+      res = LLVMBuildFMul(builder, src,
+                          lp_build_const_vec(gallivm, src_type, scale), "");
       res = LLVMBuildFPToSI(builder, res, int_vec_type, "");
    }
    else {
@@ -166,7 +169,8 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
       LLVMValueRef lshifted;
       LLVMValueRef rshifted;
 
-      res = LLVMBuildFMul(builder, src, lp_build_const_vec(src_type, scale), "");
+      res = LLVMBuildFMul(builder, src,
+                          lp_build_const_vec(gallivm, src_type, scale), "");
       res = LLVMBuildFPToSI(builder, res, int_vec_type, "");
 
       /*
@@ -177,7 +181,8 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
        */
       if (lshift) {
          lshifted = LLVMBuildShl(builder, res,
-                                 lp_build_const_int_vec(src_type, lshift), "");
+                                 lp_build_const_int_vec(gallivm, src_type,
+                                                        lshift), "");
       } else {
          lshifted = res;
       }
@@ -186,7 +191,8 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
        * Align the most significant bit to the right.
        */
       rshifted =  LLVMBuildAShr(builder, res,
-                                lp_build_const_int_vec(src_type, rshift), "");
+                                lp_build_const_int_vec(gallivm, src_type, rshift),
+                                "");
 
       /*
        * Subtract the MSB to the LSB, therefore re-scaling from
@@ -206,13 +212,14 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
  * return {float, float, float, float} with values in range [0, 1].
  */
 LLVMValueRef
-lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
+lp_build_unsigned_norm_to_float(struct gallivm_state *gallivm,
                                 unsigned src_width,
                                 struct lp_type dst_type,
                                 LLVMValueRef src)
 {
-   LLVMTypeRef vec_type = lp_build_vec_type(dst_type);
-   LLVMTypeRef int_vec_type = lp_build_int_vec_type(dst_type);
+   LLVMBuilderRef builder = gallivm->builder;
+   LLVMTypeRef vec_type = lp_build_vec_type(gallivm, dst_type);
+   LLVMTypeRef int_vec_type = lp_build_int_vec_type(gallivm, dst_type);
    LLVMValueRef bias_;
    LLVMValueRef res;
    unsigned mantissa;
@@ -224,42 +231,53 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
 
    assert(dst_type.floating);
 
-   /* Special-case int8->float, though most cases could be handled
-    * this way:
-    */
-   if (src_width == 8) {
-      scale = 1.0/255.0;
+   mantissa = lp_mantissa(dst_type);
+
+   if (src_width <= (mantissa + 1)) {
+      /*
+       * The source width matches fits what can be represented in floating
+       * point (i.e., mantissa + 1 bits). So do a straight multiplication
+       * followed by casting. No further rounding is necessary.
+       */
+
+      scale = 1.0/(double)((1ULL << src_width) - 1);
       res = LLVMBuildSIToFP(builder, src, vec_type, "");
-      res = LLVMBuildFMul(builder, res, lp_build_const_vec(dst_type, scale), "");
+      res = LLVMBuildFMul(builder, res,
+                          lp_build_const_vec(gallivm, dst_type, scale), "");
       return res;
    }
+   else {
+      /*
+       * The source width exceeds what can be represented in floating
+       * point. So truncate the incoming values.
+       */
 
-   mantissa = lp_mantissa(dst_type);
-
-   n = MIN2(mantissa, src_width);
+      n = MIN2(mantissa, src_width);
 
-   ubound = ((unsigned long long)1 << n);
-   mask = ubound - 1;
-   scale = (double)ubound/mask;
-   bias = (double)((unsigned long long)1 << (mantissa - n));
+      ubound = ((unsigned long long)1 << n);
+      mask = ubound - 1;
+      scale = (double)ubound/mask;
+      bias = (double)((unsigned long long)1 << (mantissa - n));
 
-   res = src;
+      res = src;
 
-   if(src_width > mantissa) {
-      int shift = src_width - mantissa;
-      res = LLVMBuildLShr(builder, res, lp_build_const_int_vec(dst_type, shift), "");
-   }
+      if (src_width > mantissa) {
+         int shift = src_width - mantissa;
+         res = LLVMBuildLShr(builder, res,
+                             lp_build_const_int_vec(gallivm, dst_type, shift), "");
+      }
 
-   bias_ = lp_build_const_vec(dst_type, bias);
+      bias_ = lp_build_const_vec(gallivm, dst_type, bias);
 
-   res = LLVMBuildOr(builder,
-                     res,
-                     LLVMBuildBitCast(builder, bias_, int_vec_type, ""), "");
+      res = LLVMBuildOr(builder,
+                        res,
+                        LLVMBuildBitCast(builder, bias_, int_vec_type, ""), "");
 
-   res = LLVMBuildBitCast(builder, res, vec_type, "");
+      res = LLVMBuildBitCast(builder, res, vec_type, "");
 
-   res = LLVMBuildFSub(builder, res, bias_, "");
-   res = LLVMBuildFMul(builder, res, lp_build_const_vec(dst_type, scale), "");
+      res = LLVMBuildFSub(builder, res, bias_, "");
+      res = LLVMBuildFMul(builder, res, lp_build_const_vec(gallivm, dst_type, scale), "");
+   }
 
    return res;
 }
@@ -272,12 +290,13 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
  * to the lp_type union.
  */
 void
-lp_build_conv(LLVMBuilderRef builder,
+lp_build_conv(struct gallivm_state *gallivm,
               struct lp_type src_type,
               struct lp_type dst_type,
               const LLVMValueRef *src, unsigned num_srcs,
               LLVMValueRef *dst, unsigned num_dsts)
 {
+   LLVMBuilderRef builder = gallivm->builder;
    struct lp_type tmp_type;
    LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH];
    unsigned num_tmps;
@@ -342,12 +361,12 @@ lp_build_conv(LLVMBuilderRef builder,
          int32_type.length /= 4;
          int32_type.sign = 1;
 
-         src_vec_type   = lp_build_vec_type(src_type);
-         dst_vec_type   = lp_build_vec_type(dst_type);
-         int16_vec_type = lp_build_vec_type(int16_type);
-         int32_vec_type = lp_build_vec_type(int32_type);
+         src_vec_type   = lp_build_vec_type(gallivm, src_type);
+         dst_vec_type   = lp_build_vec_type(gallivm, dst_type);
+         int16_vec_type = lp_build_vec_type(gallivm, int16_type);
+         int32_vec_type = lp_build_vec_type(gallivm, int32_type);
 
-         const_255f = lp_build_const_vec(src_type, 255.0f);
+         const_255f = lp_build_const_vec(gallivm, src_type, 255.0f);
 
          a = LLVMBuildFMul(builder, src[0], const_255f, "");
          b = LLVMBuildFMul(builder, src[1], const_255f, "");
@@ -357,14 +376,14 @@ lp_build_conv(LLVMBuilderRef builder,
          {
             struct lp_build_context bld;
 
-            bld.builder = builder;
+            bld.gallivm = gallivm;
             bld.type = src_type;
             bld.vec_type = src_vec_type;
-            bld.int_elem_type = lp_build_elem_type(int32_type);
+            bld.int_elem_type = lp_build_elem_type(gallivm, int32_type);
             bld.int_vec_type = int32_vec_type;
-            bld.undef = lp_build_undef(src_type);
-            bld.zero = lp_build_zero(src_type);
-            bld.one = lp_build_one(src_type);
+            bld.undef = lp_build_undef(gallivm, src_type);
+            bld.zero = lp_build_zero(gallivm, src_type);
+            bld.one = lp_build_one(gallivm, src_type);
 
             src_int0 = lp_build_iround(&bld, a);
             src_int1 = lp_build_iround(&bld, b);
@@ -372,9 +391,9 @@ lp_build_conv(LLVMBuilderRef builder,
             src_int3 = lp_build_iround(&bld, d);
          }
          /* relying on clamping behavior of sse2 intrinsics here */
-         lo = lp_build_pack2(builder, int32_type, int16_type, src_int0, src_int1);
-         hi = lp_build_pack2(builder, int32_type, int16_type, src_int2, src_int3);
-         dst[i] = lp_build_pack2(builder, int16_type, dst_type, lo, hi);
+         lo = lp_build_pack2(gallivm, int32_type, int16_type, src_int0, src_int1);
+         hi = lp_build_pack2(gallivm, int32_type, int16_type, src_int2, src_int3);
+         dst[i] = lp_build_pack2(gallivm, int16_type, dst_type, lo, hi);
       }
       return; 
    }
@@ -391,13 +410,13 @@ lp_build_conv(LLVMBuilderRef builder,
       double dst_max = lp_const_max(dst_type);
       LLVMValueRef thres;
 
-      lp_build_context_init(&bld, builder, tmp_type);
+      lp_build_context_init(&bld, gallivm, tmp_type);
 
       if(src_min < dst_min) {
          if(dst_min == 0.0)
             thres = bld.zero;
          else
-            thres = lp_build_const_vec(src_type, dst_min);
+            thres = lp_build_const_vec(gallivm, src_type, dst_min);
          for(i = 0; i < num_tmps; ++i)
             tmp[i] = lp_build_max(&bld, tmp[i], thres);
       }
@@ -406,7 +425,7 @@ lp_build_conv(LLVMBuilderRef builder,
          if(dst_max == 1.0)
             thres = bld.one;
          else
-            thres = lp_build_const_vec(src_type, dst_max);
+            thres = lp_build_const_vec(gallivm, src_type, dst_max);
          for(i = 0; i < num_tmps; ++i)
             tmp[i] = lp_build_min(&bld, tmp[i], thres);
       }
@@ -422,7 +441,7 @@ lp_build_conv(LLVMBuilderRef builder,
    else if(tmp_type.floating) {
       if(!dst_type.fixed && !dst_type.sign && dst_type.norm) {
          for(i = 0; i < num_tmps; ++i) {
-            tmp[i] = lp_build_clamped_float_to_unsigned_norm(builder,
+            tmp[i] = lp_build_clamped_float_to_unsigned_norm(gallivm,
                                                              tmp_type,
                                                              dst_type.width,
                                                              tmp[i]);
@@ -434,14 +453,14 @@ lp_build_conv(LLVMBuilderRef builder,
          LLVMTypeRef tmp_vec_type;
 
          if (dst_scale != 1.0) {
-            LLVMValueRef scale = lp_build_const_vec(tmp_type, dst_scale);
+            LLVMValueRef scale = lp_build_const_vec(gallivm, tmp_type, dst_scale);
             for(i = 0; i < num_tmps; ++i)
                tmp[i] = LLVMBuildFMul(builder, tmp[i], scale, "");
          }
 
          /* Use an equally sized integer for intermediate computations */
          tmp_type.floating = FALSE;
-         tmp_vec_type = lp_build_vec_type(tmp_type);
+         tmp_vec_type = lp_build_vec_type(gallivm, tmp_type);
          for(i = 0; i < num_tmps; ++i) {
 #if 0
             if(dst_type.sign)
@@ -461,7 +480,8 @@ lp_build_conv(LLVMBuilderRef builder,
 
       /* FIXME: compensate different offsets too */
       if(src_shift > dst_shift) {
-         LLVMValueRef shift = lp_build_const_int_vec(tmp_type, src_shift - dst_shift);
+         LLVMValueRef shift = lp_build_const_int_vec(gallivm, tmp_type,
+                                                     src_shift - dst_shift);
          for(i = 0; i < num_tmps; ++i)
             if(src_type.sign)
                tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, "");
@@ -485,7 +505,7 @@ lp_build_conv(LLVMBuilderRef builder,
       new_type.width  = dst_type.width;
       new_type.length = dst_type.length;
 
-      lp_build_resize(builder, tmp_type, new_type, tmp, num_srcs, tmp, num_dsts);
+      lp_build_resize(gallivm, tmp_type, new_type, tmp, num_srcs, tmp, num_dsts);
 
       tmp_type = new_type;
       num_tmps = num_dsts;
@@ -501,7 +521,7 @@ lp_build_conv(LLVMBuilderRef builder,
    else if(!src_type.floating && dst_type.floating) {
       if(!src_type.fixed && !src_type.sign && src_type.norm) {
          for(i = 0; i < num_tmps; ++i) {
-            tmp[i] = lp_build_unsigned_norm_to_float(builder,
+            tmp[i] = lp_build_unsigned_norm_to_float(gallivm,
                                                      src_type.width,
                                                      dst_type,
                                                      tmp[i]);
@@ -515,7 +535,7 @@ lp_build_conv(LLVMBuilderRef builder,
          /* Use an equally sized integer for intermediate computations */
          tmp_type.floating = TRUE;
          tmp_type.sign = TRUE;
-         tmp_vec_type = lp_build_vec_type(tmp_type);
+         tmp_vec_type = lp_build_vec_type(gallivm, tmp_type);
          for(i = 0; i < num_tmps; ++i) {
 #if 0
             if(dst_type.sign)
@@ -529,7 +549,7 @@ lp_build_conv(LLVMBuilderRef builder,
           }
 
           if (src_scale != 1.0) {
-             LLVMValueRef scale = lp_build_const_vec(tmp_type, 1.0/src_scale);
+             LLVMValueRef scale = lp_build_const_vec(gallivm, tmp_type, 1.0/src_scale);
              for(i = 0; i < num_tmps; ++i)
                 tmp[i] = LLVMBuildFMul(builder, tmp[i], scale, "");
           }
@@ -541,7 +561,7 @@ lp_build_conv(LLVMBuilderRef builder,
 
        /* FIXME: compensate different offsets too */
        if(src_shift < dst_shift) {
-          LLVMValueRef shift = lp_build_const_int_vec(tmp_type, dst_shift - src_shift);
+          LLVMValueRef shift = lp_build_const_int_vec(gallivm, tmp_type, dst_shift - src_shift);
           for(i = 0; i < num_tmps; ++i)
              tmp[i] = LLVMBuildShl(builder, tmp[i], shift, "");
        }
@@ -565,7 +585,7 @@ lp_build_conv(LLVMBuilderRef builder,
  * This is basically a very trimmed down version of lp_build_conv.
  */
 void
-lp_build_conv_mask(LLVMBuilderRef builder,
+lp_build_conv_mask(struct gallivm_state *gallivm,
                    struct lp_type src_type,
                    struct lp_type dst_type,
                    const LLVMValueRef *src, unsigned num_srcs,
@@ -599,11 +619,11 @@ lp_build_conv_mask(LLVMBuilderRef builder,
 
    if(src_type.width > dst_type.width) {
       assert(num_dsts == 1);
-      dst[0] = lp_build_pack(builder, src_type, dst_type, TRUE, src, num_srcs);
+      dst[0] = lp_build_pack(gallivm, src_type, dst_type, TRUE, src, num_srcs);
    }
    else if(src_type.width < dst_type.width) {
       assert(num_srcs == 1);
-      lp_build_unpack(builder, src_type, dst_type, src[0], dst, num_dsts);
+      lp_build_unpack(gallivm, src_type, dst_type, src[0], dst, num_dsts);
    }
    else {
       assert(num_srcs == num_dsts);