[llvm-dev] [InstCombine] addrspacecast assumed associative with gep

Nicolai Hähnle-Montoro via llvm-dev llvm-dev at lists.llvm.org
Mon Jun 17 05:10:31 PDT 2019


On Mon, Jun 17, 2019 at 8:37 AM via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> > What do you mean exactly by "behave differently on the other side of the cast”?  Do you have a concrete example?
>
> I was hesitant to say only in that it is probably an "abuse of mechanics" and definitely playing with fire, _however_ the target I'm working on has extensive bit operations for a subset of memory, including atomic test-and-set, etc. It's convenient to be able to pass around addresses of these bits, in particular for handling SFRs and interfacing with peripherals that require the use of these instructions. I know this could be handled with intrinsic functions (as with much in LLVM), however this removes the opportunity for globally allocating low cost atomic flags.
>
> Modelled as address spaces, p0 and p<bit> would have different CHAR_BITs, of 8 and 1 respectively. This somewhat works as one would expect too, with, ((bit *)&somevalue)[3] producing bit3 of somevalue - at least until the first time you access through a struct or array:
>
>         gep(addrspacecast(gep p0, 4) to p<bit>, 3) == (p0 + 4) * 8 + 3
>
> As LLVM optimises this expression to:
>
>         addrspacecast(gep p0, 4 + 3) to p<bit>
>
> Producing something entirely different.

I'm trying to figure out what the actual pointer types would be in
your, and I keep coming back to the fact that the underlying problem
here seems to be that the meaning of i1 in memory is horribly
confused...

That is, I suspect that the inner gep in your first example should be
an i8 gep and the outer gep should be an i1 gep, which means that a
pointer bitcast is missing somewhere.

I think you're right in that we probably need to say something about
which types a gep can actually operate on in a well-defined manner, on
a per-address space basis. This may be entirely based on the byte
size.

Cheers,
Nicolai


>
> But that said, I cannot think of a case where this would be a problem _except_ where CHAR_BIT would be different in one addrspace to the other, which LLVM doesn't claim to support AFAIK. Or somewhat generalised, where pX is a subset of pY, but pY has other addressable values between each valid pX in pY.
>
> I note LLVM assumes that an address will load the same value regardless of what addrspace it is read from, which I understand as matching GPU behaviour well. I know some processors have different opcodes to retrieve/store high and low instruction words through the same pointer, which means they could not be modelled as separate addrspaces either, but rather requiring implicit functions to dereference - and this is likely to be the better way, to be fair.
>
> My personal thoughts are that LLVM should not require these assumptions of GPU-style addrspace layouts, but offer a target hook to make addrspacecast a blackbox for gep and load/store combining. Or at least spell out somewhere exactly what the rules are on addrspacecast, which seems to be what's missing at the moment - is it something that can be used to describe a form of addressable memory, or is it formally required that they share the same byte size and that if an address is castable from one addrspace to another, that those values are strict aliases of one another.
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



-- 
Lerne, wie die Welt wirklich ist,
aber vergiss niemals, wie sie sein sollte.


More information about the llvm-dev mailing list