llvmpipe: Handle more conversions.
authorJosé Fonseca <jfonseca@vmware.com>
Sat, 8 Aug 2009 22:10:59 +0000 (23:10 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Sat, 29 Aug 2009 08:21:26 +0000 (09:21 +0100)
Not all successfully yet though..

src/gallium/drivers/llvmpipe/lp_bld_conv.c
src/gallium/drivers/llvmpipe/lp_test_conv.c
src/gallium/drivers/llvmpipe/lp_test_main.c

index 21918be..10a8d61 100644 (file)
@@ -50,6 +50,7 @@
 #include "lp_bld_type.h"
 #include "lp_bld_const.h"
 #include "lp_bld_intr.h"
+#include "lp_bld_arit.h"
 #include "lp_bld_conv.h"
 
 
@@ -164,8 +165,16 @@ lp_build_trunc(LLVMBuilderRef builder,
          LLVMValueRef packed = NULL;
 
          if(src_type.width == 32) {
-            /* FIXME: we only have a packed signed intrinsic */
+#if 0
+            if(dst_type.sign)
+               packed = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", tmp_vec_type, lo, hi);
+            else {
+               /* XXX: PACKUSDW intrinsic is actually the only one with a consistent signature */
+               packed = lp_build_intrinsic_binary(builder, "llvm.x86.sse41.packusdw", new_vec_type, lo, hi);
+            }
+#else
             packed = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", tmp_vec_type, lo, hi);
+#endif
          }
          else if(src_type.width == 16) {
             if(dst_type.sign)
@@ -229,8 +238,17 @@ lp_build_conv(LLVMBuilderRef builder,
     * Clamp if necessary
     */
 
-   if(!tmp_type.norm && dst_type.norm) {
-      /* FIXME */
+   if(tmp_type.sign != dst_type.sign || tmp_type.norm != dst_type.norm) {
+      struct lp_build_context bld;
+      lp_build_context_init(&bld, builder, tmp_type);
+
+      if(tmp_type.sign && !dst_type.sign)
+         for(i = 0; i < num_tmps; ++i)
+            tmp[i] = lp_build_max(&bld, tmp[i], bld.zero);
+
+      if(!tmp_type.norm && dst_type.norm)
+         for(i = 0; i < num_tmps; ++i)
+            tmp[i] = lp_build_min(&bld, tmp[i], bld.one);
    }
 
    /*
@@ -284,7 +302,7 @@ lp_build_conv(LLVMBuilderRef builder,
     * Truncate or expand bit width
     */
 
-   assert(!tmp_type.floating);
+   assert(!tmp_type.floating || tmp_type.width == dst_type.width);
 
    if(tmp_type.width > dst_type.width) {
       assert(num_dsts == 1);
@@ -345,7 +363,7 @@ lp_build_conv(LLVMBuilderRef builder,
 
        /* FIXME: compensate different offsets too */
        if(src_shift < dst_shift) {
-          LLVMValueRef shift = lp_build_int_const_uni(tmp_type, src_shift - dst_shift);
+          LLVMValueRef shift = lp_build_int_const_uni(tmp_type, dst_shift - src_shift);
           for(i = 0; i < num_tmps; ++i)
              tmp[i] = LLVMBuildShl(builder, tmp[i], shift, "");
        }
index 3dd521d..cb289af 100644 (file)
@@ -87,6 +87,7 @@ dump_conv_types(FILE *fp,
    fprintf(fp, " dst_type=");
    dump_type(fp, dst_type);
 
+   fprintf(fp, " ...\n");
    fflush(fp);
 }
 
@@ -189,8 +190,8 @@ test_one(unsigned verbose,
 
    provider = LLVMCreateModuleProviderForExistingModule(module);
    if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
-      dump_conv_types(stderr, src_type, dst_type);
-      fprintf(stderr, "\n");
+      if(verbose < 1)
+         dump_conv_types(stderr, src_type, dst_type);
       fprintf(stderr, "%s\n", error);
       LLVMDisposeMessage(error);
       abort();
@@ -248,8 +249,8 @@ test_one(unsigned verbose,
       }
 
       if (!success) {
-         dump_conv_types(stderr, src_type, dst_type);
-         fprintf(stderr, "\n");
+         if(verbose < 1)
+            dump_conv_types(stderr, src_type, dst_type);
          fprintf(stderr, "MISMATCH\n");
 
          for(j = 0; j < num_srcs; ++j) {
@@ -258,9 +259,12 @@ test_one(unsigned verbose,
             fprintf(stderr, "\n");
          }
 
+#if 0
+         fprintf(stderr, "  Ref:  ", j);
          for(j = 0; j < src_type.length*num_srcs; ++j)
             fprintf(stderr, " %f", fref[j]);
          fprintf(stderr, "\n");
+#endif
 
          for(j = 0; j < num_dsts; ++j) {
             fprintf(stderr, "  Dst%u: ", j);
@@ -305,23 +309,20 @@ test_one(unsigned verbose,
 
    }
 
-   if(verbose >= 1) {
-      fprintf(stdout, " cycles=%.1f", cycles_avg);
-   }
-
-   if(verbose >= 1) {
-      fprintf(stdout, " result=%s\n", success ? "pass" : "fail");
-      fflush(stdout);
-   }
-
    if(fp)
       write_tsv_row(fp, src_type, dst_type, cycles_avg, success);
 
    if (!success) {
-      LLVMDumpModule(module);
-      LLVMWriteBitcodeToFile(module, "conv.bc");
-      fprintf(stderr, "conv.bc written\n");
-      abort();
+      static boolean firsttime = TRUE;
+      if(firsttime) {
+         if(verbose < 2)
+            LLVMDumpModule(module);
+         LLVMWriteBitcodeToFile(module, "conv.bc");
+         fprintf(stderr, "conv.bc written\n");
+         fprintf(stderr, "Invoke as \"llc -o - conv.bc\"\n");
+         firsttime = FALSE;
+         //abort();
+      }
    }
 
    LLVMFreeMachineCodeForFunction(engine, func);
@@ -336,8 +337,26 @@ test_one(unsigned verbose,
 
 const union lp_type conv_types[] = {
    /* float, fixed,  sign,  norm, width, len */
-   {{  TRUE, FALSE,  TRUE,  TRUE,    32,   4 }}, /* f32 x 4 */
-   {{ FALSE, FALSE, FALSE,  TRUE,     8,  16 }}, /* u8n x 16 */
+
+   {{  TRUE, FALSE,  TRUE,  TRUE,    32,   4 }},
+   {{  TRUE, FALSE,  TRUE, FALSE,    32,   4 }},
+   {{  TRUE, FALSE, FALSE,  TRUE,    32,   4 }},
+   {{  TRUE, FALSE, FALSE, FALSE,    32,   4 }},
+
+   {{ FALSE, FALSE,  TRUE,  TRUE,    32,   4 }},
+   {{ FALSE, FALSE,  TRUE, FALSE,    32,   4 }},
+   {{ FALSE, FALSE, FALSE,  TRUE,    32,   4 }},
+   {{ FALSE, FALSE, FALSE, FALSE,    32,   4 }},
+
+   {{ FALSE, FALSE,  TRUE,  TRUE,    16,   8 }},
+   {{ FALSE, FALSE,  TRUE, FALSE,    16,   8 }},
+   {{ FALSE, FALSE, FALSE,  TRUE,    16,   8 }},
+   {{ FALSE, FALSE, FALSE, FALSE,    16,   8 }},
+
+   {{ FALSE, FALSE,  TRUE,  TRUE,     8,  16 }},
+   {{ FALSE, FALSE,  TRUE, FALSE,     8,  16 }},
+   {{ FALSE, FALSE, FALSE,  TRUE,     8,  16 }},
+   {{ FALSE, FALSE, FALSE, FALSE,     8,  16 }},
 };
 
 
@@ -357,6 +376,9 @@ test_all(unsigned verbose, FILE *fp)
          if(src_type == dst_type)
             continue;
 
+         if(src_type->norm != dst_type->norm)
+            continue;
+
          if(!test_one(verbose, fp, *src_type, *dst_type))
            success = FALSE;
 
@@ -380,7 +402,7 @@ test_some(unsigned verbose, FILE *fp, unsigned long n)
       
       do {
          dst_type = &conv_types[random() % num_types];
-      } while (src_type == dst_type);
+      } while (src_type == dst_type || src_type->norm != dst_type->norm);
 
       if(!test_one(verbose, fp, *src_type, *dst_type))
         success = FALSE;
index 34e6bf3..af94efb 100644 (file)
@@ -42,8 +42,9 @@ void
 dump_type(FILE *fp,
           union lp_type type)
 {
-   fprintf(fp, "%s%u%sx%u",
-           type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")),
+   fprintf(fp, "%s%s%u%sx%u",
+           type.sign ? (type.floating || type.fixed ? "" : "s") : "u",
+           type.floating ? "f" : (type.fixed ? "h" : "i"),
            type.width,
            type.norm ? "n" : "",
            type.length);
@@ -114,11 +115,13 @@ read_elem(union lp_type type, const void *src, unsigned index)
 
 
 void
-write_elem(union lp_type type, void *dst, unsigned index, double src)
+write_elem(union lp_type type, void *dst, unsigned index, double value)
 {
-   double scale = lp_const_scale(type);
-   double value = scale*src;
    assert(index < type.length);
+   if(!type.sign && value < 0.0)
+      value = 0.0;
+   if(type.norm && value > 1.0)
+      value = 1.0;
    if (type.floating) {
       switch(type.width) {
       case 32:
@@ -132,19 +135,21 @@ write_elem(union lp_type type, void *dst, unsigned index, double src)
       }
    }
    else {
+      double scale = lp_const_scale(type);
+      value = round(value*scale);
       if(type.sign) {
          switch(type.width) {
          case 8:
-            *((int8_t *)dst + index) = (int8_t)round(value);
+            *((int8_t *)dst + index) = (int8_t)value;
             break;
          case 16:
-            *((int16_t *)dst + index) = (int16_t)round(value);
+            *((int16_t *)dst + index) = (int16_t)value;
             break;
          case 32:
-            *((int32_t *)dst + index) = (int32_t)round(value);
+            *((int32_t *)dst + index) = (int32_t)value;
             break;
          case 64:
-            *((int64_t *)dst + index) = (int32_t)round(value);
+            *((int64_t *)dst + index) = (int32_t)value;
             break;
          default:
             assert(0);
@@ -153,16 +158,16 @@ write_elem(union lp_type type, void *dst, unsigned index, double src)
       else {
          switch(type.width) {
          case 8:
-            *((uint8_t *)dst + index) = (uint8_t)round(value);
+            *((uint8_t *)dst + index) = (uint8_t)value;
             break;
          case 16:
-            *((uint16_t *)dst + index) = (uint16_t)round(value);
+            *((uint16_t *)dst + index) = (uint16_t)value;
             break;
          case 32:
-            *((uint32_t *)dst + index) = (uint32_t)round(value);
+            *((uint32_t *)dst + index) = (uint32_t)value;
             break;
          case 64:
-            *((uint64_t *)dst + index) = (uint64_t)round(value);
+            *((uint64_t *)dst + index) = (uint64_t)value;
             break;
          default:
             assert(0);
@@ -175,43 +180,25 @@ write_elem(union lp_type type, void *dst, unsigned index, double src)
 void
 random_elem(union lp_type type, void *dst, unsigned index)
 {
+   double value;
    assert(index < type.length);
-   if (type.floating) {
-      double value = (double)random()/(double)RAND_MAX;
-      if(!type.norm) {
-         value += (double)random();
-         if(random() & 1)
-            value = -value;
-      }
-      switch(type.width) {
-      case 32:
-         *((float *)dst + index) = (float)value;
-         break;
-      case 64:
-          *((double *)dst + index) = value;
-         break;
-      default:
-         assert(0);
-      }
-   }
-   else {
-      switch(type.width) {
-      case 8:
-         *((uint8_t *)dst + index) = (uint8_t)random();
-         break;
-      case 16:
-         *((uint16_t *)dst + index) = (uint16_t)random();
-         break;
-      case 32:
-         *((uint32_t *)dst + index) = (uint32_t)random();
-         break;
-      case 64:
-         *((uint64_t *)dst + index) = (uint64_t)random();
-         break;
-      default:
-         assert(0);
-      }
+   value = (double)random()/(double)RAND_MAX;
+   if(!type.norm) {
+      unsigned long long mask;
+      if (type.floating)
+         mask = ~(unsigned long long)0;
+      else if (type.fixed)
+         mask = ((unsigned long long)1 << (type.width / 2)) - 1;
+      else if (type.sign)
+         mask = ((unsigned long long)1 << (type.width - 1)) - 1;
+      else
+         mask = ((unsigned long long)1 << type.width) - 1;
+      value += (double)(mask & random());
    }
+   if(!type.sign)
+      if(random() & 1)
+         value = -value;
+   write_elem(type, dst, index, value);
 }