via llvm-dev
2019-Jun-11 01:43 UTC
[llvm-dev] [InstCombine] addrspacecast assumed associative with gep
The following combine(-enabling transformation) makes me uncomfortable: gep(addrspacecast(gep p0) to p1) addrspacecast(gep(gep p0)) to p1 It's applied at visitAddrSpaceCast in InstCombineCasts.cpp. Before this, I'd always assumed address spaces were very much "user domain". Datalayout even supports marking a space as "non-integral", to designate that manipulation as bits is impossible. In my case, I have a different byte width in p1 over p0 (I know - but we all knew it was coming). All of p0 can be addressed in p1, but the reverse transformation is only sometimes possible as GEPs behave differently on the other side of the cast. This transformation of course breaks that. By my reading of ISO 18037:2006(E), it is required that if one address in p0 can be cast to p1, they all can, but I cannot find any requirements placed on the reverse operation - and further, this is a C standard, not a low-level machine. I realise this may be seen as an abuse of mechanics, but is it really intended that addrspacecast and geps can be rearranged in all circumstances, in all address space combinations? To me, the fewer assumptions made about addrspaces the better - callbacks should be used before optimising past them. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190611/fe82b500/attachment-0001.html>
Matt Arsenault via llvm-dev
2019-Jun-11 23:10 UTC
[llvm-dev] [InstCombine] addrspacecast assumed associative with gep
> On Jun 10, 2019, at 9:43 PM, via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > The following combine(-enabling transformation) makes me uncomfortable: > > gep(addrspacecast(gep p0) to p1) > > addrspacecast(gep(gep p0)) to p1 > > It's applied at visitAddrSpaceCast in InstCombineCasts.cpp. > > Before this, I'd always assumed address spaces were very much "user domain". Datalayout even supports marking a space as "non-integral", to designate that manipulation as bits is impossible. In my case, I have a different byte width in p1 over p0 (I know - but we all knew it was coming). All of p0 can be addressed in p1, but the reverse transformation is only sometimes possible as GEPs behave differently on the other side of the cast. This transformation of course breaks that.What do you mean exactly by "behave differently on the other side of the cast”? Do you have a concrete example? Questions about what’s allowed with addrspacecast arithmetic have come up before (e.g. https://reviews.llvm.org/D31924 <https://reviews.llvm.org/D31924>) but it’s never really converged into explicit guidance for the LangRef. Is this with a non-integral address space? I would like to make the LangRef clearer on what’s allowed and what’s not. Having some concrete examples would be helpful to clarify this, and possibly remove the combine. -Matt -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190611/1514606a/attachment.html>
via llvm-dev
2019-Jun-17 06:36 UTC
[llvm-dev] [InstCombine] addrspacecast assumed associative with gep
> 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. 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.
David Chisnall via llvm-dev
2019-Jun-20 09:48 UTC
[llvm-dev] [InstCombine] addrspacecast assumed associative with gep
On 12/06/2019 00:10, Matt Arsenault via llvm-dev wrote:> I would like to make the LangRef clearer on what’s allowed and what’s not.Since Matt posted this, he has indeed tried to improve the LangRef: https://reviews.llvm.org/D63525 I'd encourage anyone who is using address spaces to give feedback on this review. This is a seriously underspecified area of LLVM IR semantics and I'm *very* happy to see Matt taking the lead in improving it! David