gallivm: Add byte-swap construct calls
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Thu, 22 Nov 2012 18:23:23 +0000 (12:23 -0600)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 29 Nov 2012 11:54:14 +0000 (11:54 +0000)
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>
src/gallium/auxiliary/gallivm/lp_bld_conv.c
src/gallium/auxiliary/gallivm/lp_bld_conv.h

index cc442369630459e6f5ef640cf6764e8983a0e94c..cd18b0c652045cf1035cf8ab0fd4d2ef25ac5f50 100644 (file)
 #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;
+}
 
 
 /**
index 42a111374736b8d64cb9442c7c33a85bbea9db2a..d7dfed851872ff188e4e6bddb69eb5b24c40237e 100644 (file)
 
 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);