From 60584affcfd444e7733b01612bc72f43c83b5e06 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sat, 8 Aug 2009 23:10:59 +0100 Subject: llvmpipe: Handle more conversions. Not all successfully yet though.. --- src/gallium/drivers/llvmpipe/lp_bld_conv.c | 28 ++++++++-- src/gallium/drivers/llvmpipe/lp_test_conv.c | 62 ++++++++++++++------- src/gallium/drivers/llvmpipe/lp_test_main.c | 83 ++++++++++++----------------- 3 files changed, 100 insertions(+), 73 deletions(-) (limited to 'src') 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); } -- cgit v1.2.3