Finkel, Hal J. writes:
Can you please provide a reference to the relevant part of the OpenCL
specification describing this feature? This sounds like an extremely
surprising and problematic language design choice, and I'd like to
make sure we're not misinterpreting the specification.
Sorry, GAS compile-time resolution (inference) is not a mandatory as I
believed, and OpenCL 2.0 compiler is allowed to fallback to dynamic
resolution (generate instructions which can work with any AS).
Though it is still beneficial to infer as much as possible at compile
As Hal already mentioned, GAS is described here:
(Some specific things that are unclear here:
Where can GAS pointers be used?
Everywhere where a named pointer can be used. Only casts from GAS to a
named AS are disallowed.
Can I put them in a struct? Can I make an array of them?
Are all array elements required to point to the same address space?
Specification does not explicitly forbid this, so the answer should be:
no, elements of an array can have different address space.
Are they mutable? Can I assign pointers from multiple different
address spaces to the same GAS pointer?
Must functions taking GAS pointers be defined in the same translation
unit as the call?
No, they can be defined in different translation units.
Can different GAS parameters resolve to different address spaces?
Can you take the address of a function taking GAS pointers?)
Luckily, function pointers are not allowed in OpenCL at all.
Andrew, please correct me if I'm wrong... It looks like the answer to
all of Richard's questions is: yes.
This doesn't look like template instantiation. I retract my
recommendation in that regard.
Sorry, I was not clear about this. Specification is not clear about this
either, but from my understanding, this should work like a templates
when a GAS pointer is a function argument: if a function is called twice
with parameters of different AS, we have to duplicate the function.
which explicitly says that you get to do this:
kernel void bar(global int *g, local int *l)
var = g;
var = l;
*var = 42;
where the address space associated with a particular variable can be control-dependent. Also, it can change over time:
global int *gp;
local int *lp;
private int *pp;
p = gp; // legal
p = lp; // legal
p = pp; // legal
If you can't represent these directly (e.g., your global address space
is also your generic address space) then you might need a fat-pointer
representation which you optimize, where possible, by propagating AS
info where possible.
So you suggest to optimize address spaces in LLVM IR, and if the
optimization fails somewhere, then generate a generic code in a device
backend. Is this accurate?
This is probably the best approach, and from my understanding, this is
how it works for many OpenCL 2.0 implementations.
What I'm trying to figure out, is how to write an analysis that can
statically infer all address spaces in an "average code".
So it looks like I cannot modify Clang to make IR more friendly for this
analysis, and I need to run some optimizations to infer an address space
in more complicated cases.