diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2013-06-18 13:54:27 -0700 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2013-06-25 15:27:20 -0700 |
commit | 98adc40bb295194f42245c3b45b373655e14b4fb (patch) | |
tree | 9a789c4f07ae47fc1565fcc1b205f46f2e620ce1 | |
parent | de83d2ffc53ead3535008ac74199881c9fe4443c (diff) |
clover: Sign-extend and zero-extend kernel arguments when requiredaligned-args
-rw-r--r-- | src/gallium/state_trackers/clover/core/kernel.cpp | 23 | ||||
-rw-r--r-- | src/gallium/state_trackers/clover/core/kernel.hpp | 4 | ||||
-rw-r--r-- | src/gallium/state_trackers/clover/core/module.hpp | 10 | ||||
-rw-r--r-- | src/gallium/state_trackers/clover/llvm/invocation.cpp | 14 |
4 files changed, 45 insertions, 6 deletions
diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp index d5b256ba798..3bee3d6f2e2 100644 --- a/src/gallium/state_trackers/clover/core/kernel.cpp +++ b/src/gallium/state_trackers/clover/core/kernel.cpp @@ -33,7 +33,7 @@ _cl_kernel::_cl_kernel(clover::program &prog, prog(prog), __name(name), exec(*this) { for (auto arg : args) { if (arg.type == module::argument::scalar) - this->args.emplace_back(new scalar_argument(arg.size)); + this->args.emplace_back(new scalar_argument(arg.size, arg.ext_type)); else if (arg.type == module::argument::global) this->args.emplace_back(new global_argument(arg.size)); else if (arg.type == module::argument::local) @@ -199,8 +199,9 @@ _cl_kernel::argument::allocate_input_space(exec_context &ctx) const { return offset; } -_cl_kernel::scalar_argument::scalar_argument(size_t size) : - argument(size) { +_cl_kernel::scalar_argument::scalar_argument(size_t size, + enum module::argument::ext_type ext_type) : + argument(size), __ext_type(ext_type) { } void @@ -216,6 +217,22 @@ void _cl_kernel::scalar_argument::bind(exec_context &ctx) { size_t offset = allocate_input_space(ctx); memcpy(ctx.input.data() + offset, v.data(), __size); + + // Extend the value + bool has_sign = (ctx.input.data()[offset + __size - 1] & 0x80); + uint8_t ext_value; + if (__ext_type == module::argument::sext && has_sign) { + ext_value = 0xff; + } else { + ext_value = 0; + } + + // XXX: I'm not sure the best way to decided what size to extend the value + // to. For now we are extending everything to the the specified alignment + // size. + for (offset = offset + __size; offset < ctx.input.size(); ++offset) { + ctx.input.data()[offset] = ext_value; + } } void diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp b/src/gallium/state_trackers/clover/core/kernel.hpp index 5f196572458..0801eadba40 100644 --- a/src/gallium/state_trackers/clover/core/kernel.hpp +++ b/src/gallium/state_trackers/clover/core/kernel.hpp @@ -124,13 +124,15 @@ private: class scalar_argument : public argument { public: - scalar_argument(size_t size); + scalar_argument(size_t size, + enum clover::module::argument::ext_type ext_type); virtual void set(size_t size, const void *value); virtual void bind(exec_context &ctx); virtual void unbind(exec_context &ctx); private: + enum clover::module::argument::ext_type __ext_type; std::vector<uint8_t> v; }; diff --git a/src/gallium/state_trackers/clover/core/module.hpp b/src/gallium/state_trackers/clover/core/module.hpp index 88dfc9f3fc9..2d5186f9288 100644 --- a/src/gallium/state_trackers/clover/core/module.hpp +++ b/src/gallium/state_trackers/clover/core/module.hpp @@ -68,11 +68,19 @@ namespace clover { sampler }; - argument(enum type type, size_t size) : type(type), size(size) { } + enum ext_type { + zext, + sext, + noext, + }; + + argument(enum type type, size_t size, enum ext_type ext_type = noext) : + type(type), size(size), ext_type(ext_type) { } argument() : type(scalar), size(0) { } type type; size_t 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 2d115ed0b44..362f02f6fe3 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -321,7 +321,19 @@ namespace { break; } } else { - args.push_back(module::argument(module::argument::scalar, arg_size)); + 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, ext_type)); } } |