summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2009-08-08 23:10:59 +0100
committerJosé Fonseca <jfonseca@vmware.com>2009-08-29 09:21:26 +0100
commit60584affcfd444e7733b01612bc72f43c83b5e06 (patch)
tree29185fc6d24da73a73cdd82354031070cede2847
parent145de19548157ad1ba0c314e38a44168e462bb4c (diff)
llvmpipe: Handle more conversions.
Not all successfully yet though..
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_conv.c28
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_conv.c62
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_main.c83
3 files changed, 100 insertions, 73 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_conv.c b/src/gallium/drivers/llvmpipe/lp_bld_conv.c
index 21918be7b9..10a8d61e0d 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_conv.c
@@ -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, "");
}
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
index 3dd521d77b..cb289af857 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c
index 34e6bf31fc..af94efb8be 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_main.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_main.c
@@ -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);
}