X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fgallivm%2Flp_bld_intr.c;h=2bf1211bcd7073b028bff405a336d7cef8baee19;hb=5ae31d7e1d3d51c7843571c63aa228f8ca9b879f;hp=2323f124ae4c9d80d5dd0c2598109855f5d13cc6;hpb=9611237051e32b912f17e2d6cd23528d66ad5d81;p=mesa.git diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.c b/src/gallium/auxiliary/gallivm/lp_bld_intr.c index 2323f124ae4..2bf1211bcd7 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.c @@ -48,6 +48,8 @@ #include "lp_bld_const.h" #include "lp_bld_intr.h" +#include "lp_bld_type.h" +#include "lp_bld_pack.h" LLVMValueRef @@ -129,6 +131,95 @@ lp_build_intrinsic_binary(LLVMBuilderRef builder, } +/** + * Call intrinsic with arguments adapted to intrinsic vector length. + * + * Split vectors which are too large for the hw, or expand them if they + * are too small, so a caller calling a function which might use intrinsics + * doesn't need to do splitting/expansion on its own. + * This only supports intrinsics where src and dst types match. + */ +LLVMValueRef +lp_build_intrinsic_binary_anylength(struct gallivm_state *gallivm, + const char *name, + struct lp_type src_type, + unsigned intr_size, + LLVMValueRef a, + LLVMValueRef b) +{ + unsigned i; + struct lp_type intrin_type = src_type; + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef i32undef = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context)); + LLVMValueRef anative, bnative; + unsigned intrin_length = intr_size / src_type.width; + + intrin_type.length = intrin_length; + + if (intrin_length > src_type.length) { + LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; + LLVMValueRef constvec, tmp; + + for (i = 0; i < src_type.length; i++) { + elems[i] = lp_build_const_int32(gallivm, i); + } + for (; i < intrin_length; i++) { + elems[i] = i32undef; + } + if (src_type.length == 1) { + LLVMTypeRef elem_type = lp_build_elem_type(gallivm, intrin_type); + a = LLVMBuildBitCast(builder, a, LLVMVectorType(elem_type, 1), ""); + b = LLVMBuildBitCast(builder, b, LLVMVectorType(elem_type, 1), ""); + } + constvec = LLVMConstVector(elems, intrin_length); + anative = LLVMBuildShuffleVector(builder, a, a, constvec, ""); + bnative = LLVMBuildShuffleVector(builder, b, b, constvec, ""); + tmp = lp_build_intrinsic_binary(builder, name, + lp_build_vec_type(gallivm, intrin_type), + anative, bnative); + if (src_type.length > 1) { + constvec = LLVMConstVector(elems, src_type.length); + return LLVMBuildShuffleVector(builder, tmp, tmp, constvec, ""); + } + else { + return LLVMBuildExtractElement(builder, tmp, elems[0], ""); + } + } + else if (intrin_length < src_type.length) { + unsigned num_vec = src_type.length / intrin_length; + LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH]; + + /* don't support arbitrary size here as this is so yuck */ + if (src_type.length % intrin_length) { + /* FIXME: This is something which should be supported + * but there doesn't seem to be any need for it currently + * so crash and burn. + */ + debug_printf("%s: should handle arbitrary vector size\n", + __FUNCTION__); + assert(0); + return NULL; + } + + for (i = 0; i < num_vec; i++) { + anative = lp_build_extract_range(gallivm, a, i*intrin_length, + intrin_length); + bnative = lp_build_extract_range(gallivm, b, i*intrin_length, + intrin_length); + tmp[i] = lp_build_intrinsic_binary(builder, name, + lp_build_vec_type(gallivm, intrin_type), + anative, bnative); + } + return lp_build_concat(gallivm, tmp, intrin_type, num_vec); + } + else { + return lp_build_intrinsic_binary(builder, name, + lp_build_vec_type(gallivm, src_type), + a, b); + } +} + + LLVMValueRef lp_build_intrinsic_map(struct gallivm_state *gallivm, const char *name,