From b772d784b25771ff939e3c0c87fdf0d8053827be Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Thu, 22 Nov 2012 12:23:23 -0600 Subject: [PATCH] gallivm: Add byte-swap construct calls This patch adds two more functions in type conversions header: * lp_build_bswap: construct a call to llvm.bswap intrinsic for an element * lp_build_bswap_vec: byte swap every element in a vector base on the input and output types. Reviewed-by: Roland Scheidegger Reviewed-by: Jose Fonseca --- src/gallium/auxiliary/gallivm/lp_bld_conv.c | 78 +++++++++++++++++++++ src/gallium/auxiliary/gallivm/lp_bld_conv.h | 11 +++ 2 files changed, 89 insertions(+) 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 to convert + * @param src_type type of int16_t, int32_t, int64_t, float or + * double + * @param dst_type 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 @@ -42,6 +42,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); -- 2.30.2