diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_conv.c | 78 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_conv.h | 11 |
2 files changed, 89 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c index cc442369630..cd18b0c6520 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c @@ -71,6 +71,84 @@ #include "lp_bld_pack.h" #include "lp_bld_conv.h" #include "lp_bld_logic.h" +#include "lp_bld_intr.h" + + + +/** + * Byte swap on element. It will construct a call to intrinsic llvm.bswap + * based on the type. + * + * @param res element to byte swap. + * @param type int16_t, int32_t, int64_t, float or double + * @param + */ +LLVMValueRef +lp_build_bswap(struct gallivm_state *gallivm, + LLVMValueRef res, + struct lp_type type) +{ + LLVMTypeRef int_type = LLVMIntTypeInContext(gallivm->context, + type.width); + const char *intrinsic = NULL; + if (type.width == 8) + return res; + if (type.width == 16) + intrinsic = "llvm.bswap.i16"; + else if (type.width == 32) + intrinsic = "llvm.bswap.i32"; + else if (type.width == 64) + intrinsic = "llvm.bswap.i64"; + + assert (intrinsic != NULL); + + /* In case of a floating-point type cast to a int of same size and then + * cast back to fp type. + */ + if (type.floating) + res = LLVMBuildBitCast(gallivm->builder, res, int_type, ""); + res = lp_build_intrinsic_unary(gallivm->builder, intrinsic, int_type, res); + if (type.floating) + res = LLVMBuildBitCast(gallivm->builder, res, + lp_build_elem_type(gallivm, type), ""); + return res; +} + + +/** + * Byte swap every element in the vector. + * + * @param packed <vector> to convert + * @param src_type <vector> type of int16_t, int32_t, int64_t, float or + * double + * @param dst_type <vector> type to return + */ +LLVMValueRef +lp_build_bswap_vec(struct gallivm_state *gallivm, + LLVMValueRef packed, + struct lp_type src_type_vec, + struct lp_type dst_type_vec) +{ + LLVMBuilderRef builder = gallivm->builder; + LLVMTypeRef dst_type = lp_build_elem_type(gallivm, dst_type_vec); + LLVMValueRef res; + + if (src_type_vec.length == 1) { + res = lp_build_bswap(gallivm, packed, src_type_vec); + res = LLVMBuildBitCast(gallivm->builder, res, dst_type, ""); + } else { + unsigned i; + res = LLVMGetUndef(lp_build_vec_type(gallivm, dst_type_vec)); + for (i = 0; i < src_type_vec.length; ++i) { + LLVMValueRef index = lp_build_const_int32(gallivm, i); + LLVMValueRef elem = LLVMBuildExtractElement(builder, packed, index, ""); + elem = lp_build_bswap(gallivm, elem, src_type_vec); + elem = LLVMBuildBitCast(gallivm->builder, elem, dst_type, ""); + res = LLVMBuildInsertElement(gallivm->builder, res, elem, index, ""); + } + } + return res; +} /** diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.h b/src/gallium/auxiliary/gallivm/lp_bld_conv.h index 42a11137473..d7dfed85187 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.h @@ -43,6 +43,17 @@ struct lp_type; LLVMValueRef +lp_build_bswap(struct gallivm_state *gallivm, + LLVMValueRef res, + struct lp_type type); + +LLVMValueRef +lp_build_bswap_vec(struct gallivm_state *gallivm, + LLVMValueRef packed, + struct lp_type src_type, + struct lp_type dst_type); + +LLVMValueRef lp_build_half_to_float(struct gallivm_state *gallivm, LLVMValueRef src); |