clover: Extend kernel arguments for differing host and device data types.
authorFrancisco Jerez <currojerez@riseup.net>
Mon, 22 Jul 2013 21:08:46 +0000 (23:08 +0200)
committerFrancisco Jerez <currojerez@riseup.net>
Mon, 22 Jul 2013 21:09:34 +0000 (23:09 +0200)
Loosely based on a similar patch by Tom Stellard.

Cc: mesa-stable@lists.freedesktop.org
Reviewed-by: Tom Stellard <thomas.stellard@amd.com>
src/gallium/state_trackers/clover/core/kernel.cpp
src/gallium/state_trackers/clover/llvm/invocation.cpp

index 82e937eeea539abe30c725f59b055843c4754a2e..7023f291fe25ab80f8b95be3e672f753934064a0 100644 (file)
@@ -197,6 +197,34 @@ namespace {
          std::reverse(v.begin(), v.end());
    }
 
+   bool
+   msb(const std::vector<uint8_t> &s) {
+      if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE)
+         return s.back() & 0x80;
+      else
+         return s.front() & 0x80;
+   }
+
+   ///
+   /// Resize buffer \a v to size \a n using sign or zero extension
+   /// according to \a ext.
+   ///
+   template<typename T>
+   void
+   extend(T &v, enum clover::module::argument::ext_type ext, size_t n) {
+      const size_t m = std::min(v.size(), n);
+      const bool sign_ext = (ext == module::argument::sign_ext);
+      const uint8_t fill = (sign_ext && msb(v) ? ~0 : 0);
+      T w(n, fill);
+
+      if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE)
+         std::copy_n(v.begin(), m, w.begin());
+      else
+         std::copy_n(v.end() - m, m, w.end() - m);
+
+      std::swap(v, w);
+   }
+
    ///
    /// Append buffer \a w to \a v.
    ///
@@ -248,6 +276,7 @@ _cl_kernel::scalar_argument::bind(exec_context &ctx,
                                   const clover::module::argument &marg) {
    auto w = v;
 
+   extend(w, marg.ext_type, marg.target_size);
    byteswap(w, ctx.q->dev.endianness());
    insert(ctx.input, w);
 }
@@ -271,7 +300,7 @@ _cl_kernel::global_argument::set(size_t size, const void *value) {
 void
 _cl_kernel::global_argument::bind(exec_context &ctx,
                                   const clover::module::argument &marg) {
-   ctx.g_handles.push_back(allocate(ctx.input, marg.size));
+   ctx.g_handles.push_back(allocate(ctx.input, marg.target_size));
    ctx.g_buffers.push_back(obj->resource(ctx.q).pipe);
 }
 
@@ -298,6 +327,7 @@ _cl_kernel::local_argument::bind(exec_context &ctx,
                                  const clover::module::argument &marg) {
    auto v = bytes(ctx.mem_local);
 
+   extend(v, module::argument::zero_ext, marg.target_size);
    byteswap(v, ctx.q->dev.endianness());
    insert(ctx.input, v);
 
@@ -325,6 +355,7 @@ _cl_kernel::constant_argument::bind(exec_context &ctx,
                                     const clover::module::argument &marg) {
    auto v = bytes(ctx.resources.size() << 24);
 
+   extend(v, module::argument::zero_ext, marg.target_size);
    byteswap(v, ctx.q->dev.endianness());
    insert(ctx.input, v);
 
@@ -354,6 +385,7 @@ _cl_kernel::image_rd_argument::bind(exec_context &ctx,
                                     const clover::module::argument &marg) {
    auto v = bytes(ctx.sviews.size());
 
+   extend(v, module::argument::zero_ext, marg.target_size);
    byteswap(v, ctx.q->dev.endianness());
    insert(ctx.input, v);
 
@@ -383,6 +415,7 @@ _cl_kernel::image_wr_argument::bind(exec_context &ctx,
                                     const clover::module::argument &marg) {
    auto v = bytes(ctx.resources.size());
 
+   extend(v, module::argument::zero_ext, marg.target_size);
    byteswap(v, ctx.q->dev.endianness());
    insert(ctx.input, v);
 
index dae61f7fa7dc11e8ced6dc3cc7c1881a8496ee42..a50cf37dfcbda08bd15f65323123346e0b113f89 100644 (file)
@@ -304,14 +304,20 @@ namespace {
          for (llvm::Function::arg_iterator I = kernel_func->arg_begin(),
                                       E = kernel_func->arg_end(); I != E; ++I) {
             llvm::Argument &arg = *I;
-            llvm::Type *arg_type = arg.getType();
 #if HAVE_LLVM < 0x0302
             llvm::TargetData TD(kernel_func->getParent());
 #else
             llvm::DataLayout TD(kernel_func->getParent()->getDataLayout());
 #endif
+
+            llvm::Type *arg_type = arg.getType();
             unsigned arg_size = TD.getTypeStoreSize(arg_type);
 
+            llvm::Type *target_type = arg_type->isIntegerTy() ?
+               TD.getSmallestLegalIntType(mod->getContext(), arg_size * 8) :
+               arg_type;
+            unsigned target_size = TD.getTypeStoreSize(target_type);
+
             if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) {
                arg_type =
                   llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType();
@@ -324,11 +330,24 @@ namespace {
                unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace();
                switch (address_space) {
                   default:
-                     args.push_back(module::argument(module::argument::global, arg_size));
+                     args.push_back(
+                        module::argument(module::argument::global, arg_size,
+                                         target_size, 0,
+                                         module::argument::zero_ext));
                      break;
                }
+
             } else {
-               args.push_back(module::argument(module::argument::scalar, arg_size));
+               llvm::AttributeSet attrs = kernel_func->getAttributes();
+               enum module::argument::ext_type ext_type =
+                  (attrs.hasAttribute(arg.getArgNo() + 1,
+                                     llvm::Attribute::SExt) ?
+                   module::argument::sign_ext :
+                   module::argument::zero_ext);
+
+               args.push_back(
+                  module::argument(module::argument::scalar, arg_size,
+                                   target_size, 0, ext_type));
             }
          }