summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <thomas.stellard@amd.com>2013-06-18 13:54:27 -0700
committerTom Stellard <thomas.stellard@amd.com>2013-06-25 15:27:20 -0700
commit98adc40bb295194f42245c3b45b373655e14b4fb (patch)
tree9a789c4f07ae47fc1565fcc1b205f46f2e620ce1
parentde83d2ffc53ead3535008ac74199881c9fe4443c (diff)
clover: Sign-extend and zero-extend kernel arguments when requiredaligned-args
-rw-r--r--src/gallium/state_trackers/clover/core/kernel.cpp23
-rw-r--r--src/gallium/state_trackers/clover/core/kernel.hpp4
-rw-r--r--src/gallium/state_trackers/clover/core/module.hpp10
-rw-r--r--src/gallium/state_trackers/clover/llvm/invocation.cpp14
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));
}
}