diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_conv.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c index 8b477313d48..605eb043c73 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c @@ -69,6 +69,7 @@ #include "lp_bld_arit.h" #include "lp_bld_pack.h" #include "lp_bld_conv.h" +#include "lp_bld_intr.h" /** @@ -241,6 +242,89 @@ lp_build_conv(LLVMBuilderRef builder, } num_tmps = num_srcs; + + /* Special case 4x4f --> 1x16ub + */ + if (src_type.floating == 1 && + src_type.fixed == 0 && + src_type.sign == 1 && + src_type.norm == 0 && + src_type.width == 32 && + src_type.length == 4 && + + dst_type.floating == 0 && + dst_type.fixed == 0 && + dst_type.sign == 0 && + dst_type.norm == 1 && + dst_type.width == 8 && + dst_type.length == 16) + { + int i; + + for (i = 0; i < num_dsts; i++, src += 4) { + struct lp_type int16_type = dst_type; + struct lp_type int32_type = dst_type; + LLVMValueRef lo, hi; + LLVMValueRef src_int0; + LLVMValueRef src_int1; + LLVMValueRef src_int2; + LLVMValueRef src_int3; + LLVMTypeRef int16_vec_type; + LLVMTypeRef int32_vec_type; + LLVMTypeRef src_vec_type; + LLVMTypeRef dst_vec_type; + LLVMValueRef const_255f; + + int16_type.width *= 2; + int16_type.length /= 2; + int16_type.sign = 1; + + int32_type.width *= 4; + 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); + + const_255f = lp_build_const_vec(src_type, 255.0); + + src_int0 = LLVMBuildFPToSI(builder, + LLVMBuildFMul(builder, src[0], const_255f, ""), + int32_vec_type, ""); + + src_int1 = LLVMBuildFPToSI(builder, + LLVMBuildFMul(builder, src[1], const_255f, ""), + int32_vec_type, ""); + + src_int2 = LLVMBuildFPToSI(builder, + LLVMBuildFMul(builder, src[2], const_255f, ""), + int32_vec_type, ""); + + src_int3 = LLVMBuildFPToSI(builder, + LLVMBuildFMul(builder, src[3], const_255f, ""), + int32_vec_type, ""); + +#if HAVE_LLVM >= 0x0207 + lo = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", + int16_vec_type, src_int0, src_int1); + hi = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", + int16_vec_type, src_int2, src_int3); + dst[i] = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packuswb.128", + dst_vec_type, lo, hi); +#else + lo = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", + int32_vec_type, src_int0, src_int1); + hi = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", + int32_vec_type, src_int2, src_int3); + dst[i] = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packuswb.128", + int16_vec_type, lo, hi); +#endif + } + return; + } + /* * Clamp if necessary */ |