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 <sroland@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
Adhemerval Zanella 2012-11-22 12:23:23 -06:00 committed by José Fonseca
parent 86902b5134
commit b772d784b2
2 changed files with 89 additions and 0 deletions

View file

@ -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;
}
/**

View file

@ -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);