[Mesa-dev] [PATCH 7/7] clover: Sign-extend and zero-extend kernel arguments when required v2

Tom Stellard tom at stellard.net
Tue Jul 9 21:21:44 PDT 2013


From: Tom Stellard <thomas.stellard at amd.com>

v2:
  - Extend to target size rather than aligned size
  - Support for big-endian
---
 src/gallium/state_trackers/clover/core/kernel.cpp  | 58 ++++++++++++++++------
 src/gallium/state_trackers/clover/core/kernel.hpp  | 17 ++++---
 src/gallium/state_trackers/clover/core/module.hpp  | 27 ++++++++--
 .../state_trackers/clover/llvm/invocation.cpp      | 20 +++++++-
 4 files changed, 95 insertions(+), 27 deletions(-)

diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp
index 2b6fbe5..99723ff 100644
--- a/src/gallium/state_trackers/clover/core/kernel.cpp
+++ b/src/gallium/state_trackers/clover/core/kernel.cpp
@@ -152,10 +152,12 @@ _cl_kernel::exec_context::bind(clover::command_queue *__q) {
    for (const clover::module::argument &arg : kern.module_args(*q)) {
       if (arg.type == clover::module::argument::pad) {
          input.resize(input.size() + arg.size);
-      } else {
-         assert(arg.arg_index >= 0);
-         kern.args[arg.arg_index]->bind(*this);
+         break;
       }
+
+      assert(arg.arg_index >= 0);
+
+      kern.args[arg.arg_index]->bind(*this, arg);
    }
 
    // Create a new compute state if anything changed.
@@ -202,9 +204,7 @@ _cl_kernel::argument::storage() const {
    return 0;
 }
 
-_cl_kernel::scalar_argument::scalar_argument(size_t size) :
-   argument(size) {
-}
+_cl_kernel::scalar_argument::scalar_argument(size_t size) : argument(size) { }
 
 void
 _cl_kernel::scalar_argument::set(size_t size, const void *value) {
@@ -216,8 +216,32 @@ _cl_kernel::scalar_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::scalar_argument::bind(exec_context &ctx) {
-   ctx.input.insert(ctx.input.end(), v.begin(), v.end());
+_cl_kernel::scalar_argument::bind(exec_context &ctx,
+                                  const clover::module::argument &arg) {
+   // Extend the value
+   bool little_endian = ctx.q->dev.endianness() == PIPE_ENDIAN_LITTLE;
+   bool has_sign;
+   if (little_endian) {
+      has_sign = v[__size - 1] & 0x80;
+   } else {
+      has_sign = v[0] & 0x80;
+   }
+   uint8_t ext_value;
+   if (arg.ext_type == module::argument::sext && has_sign) {
+      ext_value = 0xff;
+   } else {
+      ext_value = 0;
+   }
+
+   if (little_endian) {
+      ctx.input.insert(ctx.input.end(), v.begin(), v.end());
+   }
+   for (unsigned i = __size; i < arg.target_size; ++i) {
+      ctx.input.push_back(ext_value);
+   }
+   if (!little_endian) {
+      ctx.input.insert(ctx.input.end(), v.begin(), v.end());
+   }
 }
 
 void
@@ -241,7 +265,8 @@ _cl_kernel::global_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::global_argument::bind(exec_context &ctx) {
+_cl_kernel::global_argument::bind(exec_context &ctx,
+                                  const clover::module::argument &arg) {
    size_t offset = ctx.input.size();
    size_t idx = ctx.g_buffers.size();
 
@@ -277,7 +302,8 @@ _cl_kernel::local_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::local_argument::bind(exec_context &ctx) {
+_cl_kernel::local_argument::bind(exec_context &ctx,
+                                  const clover::module::argument &arg) {
    size_t offset = ctx.input.size();
    size_t ptr = ctx.mem_local;
 
@@ -308,7 +334,8 @@ _cl_kernel::constant_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::constant_argument::bind(exec_context &ctx) {
+_cl_kernel::constant_argument::bind(exec_context &ctx,
+                                  const clover::module::argument &arg) {
    size_t offset = ctx.input.size();
    size_t idx = ctx.resources.size();
 
@@ -341,7 +368,8 @@ _cl_kernel::image_rd_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::image_rd_argument::bind(exec_context &ctx) {
+_cl_kernel::image_rd_argument::bind(exec_context &ctx,
+                                  const clover::module::argument &arg) {
    size_t offset = ctx.input.size();
    size_t idx = ctx.sviews.size();
 
@@ -374,7 +402,8 @@ _cl_kernel::image_wr_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::image_wr_argument::bind(exec_context &ctx) {
+_cl_kernel::image_wr_argument::bind(exec_context &ctx,
+                                    const clover::module::argument &arg) {
    size_t offset = ctx.input.size();
    size_t idx = ctx.resources.size();
 
@@ -404,7 +433,8 @@ _cl_kernel::sampler_argument::set(size_t size, const void *value) {
 }
 
 void
-_cl_kernel::sampler_argument::bind(exec_context &ctx) {
+_cl_kernel::sampler_argument::bind(exec_context &ctx,
+                                   const clover::module::argument &arg) {
    size_t idx = ctx.samplers.size();
 
    ctx.samplers.resize(idx + 1);
diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp b/src/gallium/state_trackers/clover/core/kernel.hpp
index 2c540be..2ccd027 100644
--- a/src/gallium/state_trackers/clover/core/kernel.hpp
+++ b/src/gallium/state_trackers/clover/core/kernel.hpp
@@ -84,7 +84,8 @@ public:
 
       /// Allocate the necessary resources to bind the specified
       /// object to this argument, and update \a ctx accordingly.
-      virtual void bind(exec_context &ctx) = 0;
+      virtual void bind(exec_context &ctx,
+                        const clover::module::argument &arg) = 0;
 
       /// Free any resources that were allocated in bind().
       virtual void unbind(exec_context &ctx) = 0;
@@ -125,7 +126,7 @@ private:
       scalar_argument(size_t size);
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
@@ -137,7 +138,7 @@ private:
       global_argument(size_t size);
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
@@ -151,7 +152,7 @@ private:
       virtual size_t storage() const;
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
@@ -163,7 +164,7 @@ private:
       constant_argument(size_t size);
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
@@ -176,7 +177,7 @@ private:
       image_rd_argument(size_t size);
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
@@ -189,7 +190,7 @@ private:
       image_wr_argument(size_t size);
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
@@ -202,7 +203,7 @@ private:
       sampler_argument(size_t size);
 
       virtual void set(size_t size, const void *value);
-      virtual void bind(exec_context &ctx);
+      virtual void bind(exec_context &ctx, const clover::module::argument &arg);
       virtual void unbind(exec_context &ctx);
 
    private:
diff --git a/src/gallium/state_trackers/clover/core/module.hpp b/src/gallium/state_trackers/clover/core/module.hpp
index d4b3413..c880315 100644
--- a/src/gallium/state_trackers/clover/core/module.hpp
+++ b/src/gallium/state_trackers/clover/core/module.hpp
@@ -69,17 +69,36 @@ namespace clover {
             pad
          };
 
+         enum ext_type {
+            zext,
+            sext,
+            noext,
+         };
+
+         argument(enum type type, size_t size, size_t arg_index,
+                  size_t target_size, enum ext_type ext_type) : type(type),
+                                size(size), arg_index(arg_index),
+                                target_size(target_size), ext_type(ext_type) { }
          argument(enum type type, size_t size, size_t arg_index) : type(type),
-                      size(size), arg_index(arg_index) { }
-         argument(enum type type, size_t size) : type(type), size(size),
-                      arg_index(-1) { }
-         argument() : type(scalar), size(0), arg_index(-1) { }
+                      size(size), arg_index(arg_index), target_size(size),
+                      ext_type(noext) { }
+         argument(enum type type, size_t size) : type(type),
+                      size(size), arg_index(-1), target_size(size),
+                      ext_type(noext) { }
+         argument() : type(scalar), size(0), arg_index(-1), target_size(0),
+                      ext_type(noext) { }
 
          type type;
          size_t size;
          /// The index of this argument in the function.  If arg_index is -1,
          /// then this arguement is not a formal argument of the function.
          size_t arg_index;
+
+         /// The size of this argument in the target architecture.  This will
+         /// typically be the smallest natively supported integer size of a
+         /// target.
+         size_t target_size;
+         ext_type ext_type;
       };
 
       struct symbol {
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 68f7eac..16198e0 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -344,8 +344,26 @@ namespace {
                      break;
                }
             } else {
+               unsigned attr_index = arg.getArgNo() + 1;
+               // Determine the argument's alignment.  When the SExt or ZExt
+               // attribute is set on a function, it means that the caller must
+               // extend the value to the appropriate size.  We will extend the
+               // value when binding it to a kernel.
+               // See _cl_kernel::scalar_argument::bind()
+               enum module::argument::ext_type ext_type =
+                                                        module::argument::noext;
+
+               if (kernel_func->getAttributes().hasAttribute(attr_index,
+                                                       llvm::Attribute::SExt)) {
+                  ext_type = module::argument::sext;
+               } else if (kernel_func->getAttributes().hasAttribute(attr_index,
+                                                       llvm::Attribute::ZExt)) {
+                  ext_type = module::argument::zext;
+               }
+
                args.push_back(module::argument(module::argument::scalar,
-                                               arg_size, arg.getArgNo()));
+                                               arg_size, arg.getArgNo(),
+                                               target_size >> 3, ext_type));
             }
             if (aligned_size > target_size) {
                args.push_back(module::argument(module::argument::pad,
-- 
1.7.11.4



More information about the mesa-dev mailing list