Re: llvm calling convention matters
hey all, first let me preface by saying I am in favor of breaking and updating/modernizing the GHC ABI. I just think that for a number of reasons, it doesn't make sense to do it for the 7.8 release, but rather start work on it in another month or so, so we can systematically have a better set of ABI, and keep all the code gens are first class citizens. (also work out the type system changes need to be able to correctly use SIMD shuffles, which are currently inexpressible correctly with GHC's type system. Simd Shuffles are crucial for interesting levels of SIMD performance!) the reason I don't want to make the ABI change right now is because then we'd have to wait until after llvm 3.4 gets released in like 6 months before giving them another breaking change! (OR start baking a LLVM into GHC, which is a leap we're not 100% on, though theres clear good reasons for why! ). Basically, if we make breaking changes to the ABI now (and thus have split ABI for llvm 3.4HEAD vs earlier), and then we do fixups or more breakage for 7.10, then when 7.10 rolls around (perhaps late next spring or sometime in the summer, perhaps?), the only supported llvm version for 7.10 would be LLVM HEAD / 3.5 (which won't be released till some time thereafter)! Unless we go ahead and break the 3.4 ABI to 7.10 rather than 7.8 abi (whatever that would entai, which would ). This is assuming the ~ 7-8 months between major version releases cycle that LLVM has done of late additionally, as Johan remarked today on a pending patch of mine, having operations only work on the llvm backend, and not on the native code gen is pretty problematical! see http://ghc.haskell.org/trac/ghc/ticket/8256 tl;dr : Unless we're throwing away native code gen backend next month, we probably want to actually not increase their capability gap / current ABI incompatibility right before 7.8 release. I am willing to help explore modernizing the native code gens so that they have parity with the llvm backends. Additionally, boxing ourselves in a corner where for 7.10 the only llvm with the right ABI will be llvm 3.5 seems totally unacceptable from an end users / distribution package managers standpoint, and a huge support headache for the community. I've had to help deal with the support headache of the xcode5 clang + ghc issues on OS X, A LOT, in the past 2 months, I'm not keen on deliberately creating similar support disasters for myself and others. that said: I absolutely agree that we should fix up the ABI, have a clear story for XMM, YMM, and ZMM registers, and if you've been following trac tickets at all, you'll see theres even a type system issue in properly handling the SIMD shuffles! i briefly sketch out the issue in http://ghc.haskell.org/trac/ghc/ticket/8107 (last comment) that said: i'm open to being convinced i'm wrong, and I absolutely understand your motivations for wanting it now, but I really believe that doing so right now will create a number of problems that are better off evaded to begin with cheers -Carter On Wed, Sep 11, 2013 at 5:49 PM, Geoffrey Mainland <mainland@cs.drexel.edu>wrote:
Hi Carter,
On 09/06/2013 03:24 PM, Carter Tazio Schonwald wrote:
Hey Geoff,
I'm leary about doing a calling convention change right before the ghc release (and I"m happy to elaborate more on the phone some time) 1) I'd rather we test the patches on llvm locally ourselves before going upstream 2) doing that AVX change on the calling convention now, would make it harder to make a more systematic exploration of calling convention changes post 7.8 release, because we would face either breaking the llvm head/3.4 changes, or having to wait till the next llvm release cycle (3.5?!) to upstream any more systematic changes. (such as adding substantially more SIMD registers to the GHC calling convention!)
I understand your likely motivation for wanting the calling convention landing in the 7.8 release, namely it may eke an easy 2x perf boost in your stream fusion libs, i just worry that the change would ultimately cut off our ability to do more aggressive experimentation and improvements (eg more simd registers!) for ghc 7.10 over the next year?
on an unrelated note: I will spend some time this weekend given you the various simd operations I want / think are valuable. the low hanging fruit would be figuring out a good haskell type / analogue of the llvm __builtin_shuffle(a,b,c) primop, because that usually should generate decent code. I'll work out the details of this and some other examples and send it your way in the next few days
-Carter
Currently, on x86-64 we pass floats, doubles, and 128-bit wide SIMD vectors in xmm1-xmm6. I propose that we change the calling conventions to pass 256-bit wide SIMD vectors in ymm1-ymm6 and 512-bit wide SIMD vectors in zmm1-zmm6. I don't know why GHC doesn't use xmm0 or xmm7, as the Linux C calling convention uses xmm0-xmm7. Simon, perhaps you know why? I get that we only needed 6 registers originally, F1-F4, D1-D2), but why count from one rather than zero?
On x86-32, we pass floats, double, and all SIMD vectors on the stack. I propose that we pass 128-bit wide SIMD vectors in xmm0-xmm2, and make analogous arrangements for 256- and 512-bit SIMD vectors. We will still pass floats and doubles on the stack. This matches the Linux x86 32-bit C calling convention.
I think these are fairly conservative changes. I also don't think we should be afraid of revising the calling convention for GHC 7.10. Surely the LLVM folks won't be upset if we send them one set of patches a year instead of one set of patches every two years.
Geoff
Can you provide an example of the kind of ABI change you might want for 7.10? Is it mainly using more registers to pass arguments? We're already using 6 *mm* registers to pass arguments on x86_64. I don't know for sure, but I would be very surprised if there is code out there that would benefit greatly from passing more than 6 Float/Double/SIMD vector arguments in registers. Without understanding the ABI design space you have in mind, I can't comment on how changing the ABI now would or would not make future exploration more difficult. I don't see why we should limit ourselves by insisting that the gap between what the LLVM back-end and the native back-end not grow further. If we want SIMD, the gap is already quite large. Yes it would be nice to have feature parity, but there are only so many man-hours available, and we want to invest them wisely. The SIMD primops already do not work on the native codegen; the user gets an error telling them to use the LLVM back-end if they use the SIMD primops with the native codegen. I was not suggesting that we require LLVM 3.4 or later for this or any future version of GHC. Instead, the ABI would change based on the version of LLVM used. I think that is unavoidable at this point and not a huge deal as it would only affect SIMD code. All this said, I'm not going to push. Changing the ABI just creates more work for me. I'm very motivated to get the rest of the SIMD patches into HEAD before I present our SIMD paper at ICFP in a few weeks. However, a year from now my priorities will likely be very different, so the ball will be entirely in your (or someone else's, just not my!) court. Geoff On 09/11/2013 06:26 PM, Carter Schonwald wrote:
hey all,
first let me preface by saying I am in favor of breaking and updating/modernizing the GHC ABI.
I just think that for a number of reasons, it doesn't make sense to do it for the 7.8 release, but rather start work on it in another month or so, so we can systematically have a better set of ABI, and keep all the code gens are first class citizens. (also work out the type system changes need to be able to correctly use SIMD shuffles, which are currently inexpressible correctly with GHC's type system. Simd Shuffles are crucial for interesting levels of SIMD performance!)
the reason I don't want to make the ABI change right now is because then we'd have to wait until after llvm 3.4 gets released in like 6 months before giving them another breaking change! (OR start baking a LLVM into GHC, which is a leap we're not 100% on, though theres clear good reasons for why! ).
Basically, if we make breaking changes to the ABI now (and thus have split ABI for llvm 3.4HEAD vs earlier), and then we do fixups or more breakage for 7.10, then when 7.10 rolls around (perhaps late next spring or sometime in the summer, perhaps?), the only supported llvm version for 7.10 would be LLVM HEAD / 3.5 (which won't be released till some time thereafter)! Unless we go ahead and break the 3.4 ABI to 7.10 rather than 7.8 abi (whatever that would entai, which would ). This is assuming the ~ 7-8 months between major version releases cycle that LLVM has done of late
additionally, as Johan remarked today on a pending patch of mine, having operations only work on the llvm backend, and not on the native code gen is pretty problematical! see http://ghc.haskell.org/trac/ghc/ticket/8256
tl;dr : Unless we're throwing away native code gen backend next month, we probably want to actually not increase their capability gap / current ABI incompatibility right before 7.8 release. I am willing to help explore modernizing the native code gens so that they have parity with the llvm backends. Additionally, boxing ourselves in a corner where for 7.10 the only llvm with the right ABI will be llvm 3.5 seems totally unacceptable from an end users / distribution package managers standpoint, and a huge support headache for the community.
I've had to help deal with the support headache of the xcode5 clang + ghc issues on OS X, A LOT, in the past 2 months, I'm not keen on deliberately creating similar support disasters for myself and others.
that said: I absolutely agree that we should fix up the ABI, have a clear story for XMM, YMM, and ZMM registers, and if you've been following trac tickets at all, you'll see theres even a type system issue in properly handling the SIMD shuffles! i briefly sketch out the issue in http://ghc.haskell.org/trac/ghc/ticket/8107 (last comment)
that said: i'm open to being convinced i'm wrong, and I absolutely understand your motivations for wanting it now, but I really believe that doing so right now will create a number of problems that are better off evaded to begin with
cheers -Carter
On Wed, Sep 11, 2013 at 5:49 PM, Geoffrey Mainland <mainland@cs.drexel.edu <mailto:mainland@cs.drexel.edu>> wrote:
Hi Carter,
On 09/06/2013 03:24 PM, Carter Tazio Schonwald wrote: > Hey Geoff,
> I'm leary about doing a calling convention change right before the ghc > release (and I"m happy to elaborate more on the phone some time) 1) > I'd rather we test the patches on llvm locally ourselves before going > upstream 2) doing that AVX change on the calling convention now, would > make it harder to make a more systematic exploration of calling > convention changes post 7.8 release, because we would face either > breaking the llvm head/3.4 changes, or having to wait till the next > llvm release cycle (3.5?!) to upstream any more systematic > changes. (such as adding substantially more SIMD registers to the GHC > calling convention!) > > I understand your likely motivation for wanting the calling convention > landing in the 7.8 release, namely it may eke an easy 2x perf boost in > your stream fusion libs, i just worry that the change would ultimately > cut off our ability to do more aggressive experimentation and > improvements (eg more simd registers!) for ghc 7.10 over the next > year? > > on an unrelated note: I will spend some time this weekend given you > the various simd operations I want / think are valuable. the low > hanging fruit would be figuring out a good haskell type / analogue of > the llvm __builtin_shuffle(a,b,c) primop, because that usually should > generate decent code. I'll work out the details of this and some other > examples and send it your way in the next few days > > -Carter
Currently, on x86-64 we pass floats, doubles, and 128-bit wide SIMD vectors in xmm1-xmm6. I propose that we change the calling conventions to pass 256-bit wide SIMD vectors in ymm1-ymm6 and 512-bit wide SIMD vectors in zmm1-zmm6. I don't know why GHC doesn't use xmm0 or xmm7, as the Linux C calling convention uses xmm0-xmm7. Simon, perhaps you know why? I get that we only needed 6 registers originally, F1-F4, D1-D2), but why count from one rather than zero?
On x86-32, we pass floats, double, and all SIMD vectors on the stack. I propose that we pass 128-bit wide SIMD vectors in xmm0-xmm2, and make analogous arrangements for 256- and 512-bit SIMD vectors. We will still pass floats and doubles on the stack. This matches the Linux x86 32-bit C calling convention.
I think these are fairly conservative changes. I also don't think we should be afraid of revising the calling convention for GHC 7.10. Surely the LLVM folks won't be upset if we send them one set of patches a year instead of one set of patches every two years.
Geoff
On Wed, Sep 11, 2013 at 3:59 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
I don't see why we should limit ourselves by insisting that the gap between what the LLVM back-end and the native back-end not grow further. If we want SIMD, the gap is already quite large. Yes it would be nice to have feature parity, but there are only so many man-hours available, and we want to invest them wisely. The SIMD primops already do not work on the native codegen; the user gets an error telling them to use the LLVM back-end if they use the SIMD primops with the native codegen.
Having conditional primops makes for lots of ugly #ifdefs everywhere and everyone need to make sure they do these correctly. We don't have to implement SIMD in the native backend, we just need to have some reasonable emulation e.g. see how MO_PopCnt has a C fallback or how Int64 falls back to C code.
On 09/11/2013 07:33 PM, Johan Tibell wrote:
On Wed, Sep 11, 2013 at 3:59 PM, Geoffrey Mainland <mainland@apeiron.net> wrote:
I don't see why we should limit ourselves by insisting that the gap between what the LLVM back-end and the native back-end not grow further. If we want SIMD, the gap is already quite large. Yes it would be nice to have feature parity, but there are only so many man-hours available, and we want to invest them wisely. The SIMD primops already do not work on the native codegen; the user gets an error telling them to use the LLVM back-end if they use the SIMD primops with the native codegen.
Having conditional primops makes for lots of ugly #ifdefs everywhere and everyone need to make sure they do these correctly. We don't have to implement SIMD in the native backend, we just need to have some reasonable emulation e.g. see how MO_PopCnt has a C fallback or how Int64 falls back to C code.
Do you mean we need a reasonable emulation of the SIMD primops for the native codegen? Geoff
On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
Do you mean we need a reasonable emulation of the SIMD primops for the native codegen?
Yes. Reasonable in the sense that it computes the right result. I can see that some code might still want to #ifdef (if the fallback isn't fast enough).
On 09/11/2013 07:44 PM, Johan Tibell wrote:
On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland <mainland@apeiron.net> wrote:
Do you mean we need a reasonable emulation of the SIMD primops for the native codegen?
Yes. Reasonable in the sense that it computes the right result. I can see that some code might still want to #ifdef (if the fallback isn't fast enough).
Two implications of this requirement: 1) There will not be SIMD in 7.8. I just don't have the time. In fact, what SIMD support is there already will have to be removed if we cannot live with LLVM-only SIMD primops. 2) If we also require interop between the LLVM back-end and the native codegen, then we cannot pass any SIMD vectors in registers---they all must be passed on the stack. My plan, as discussed with Simon PJ, is to not support SIMD primops at all with the native codegen. If there is a strong feeling that this *is not* the way to go, the I need to know ASAP. Geoff
Do nothing different than you're doing for 7.8, we can sort it out later. Just put a comment on the primops saying they're LLVM-only. See e.g. https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 for an example how to add docs to primops. I don't think we need interop between the native and the LLVM backends. We don't have that now do we (i.e. they use different calling conventions). On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
On 09/11/2013 07:44 PM, Johan Tibell wrote:
On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland <mainland@apeiron.net> wrote:
Do you mean we need a reasonable emulation of the SIMD primops for the native codegen?
Yes. Reasonable in the sense that it computes the right result. I can see that some code might still want to #ifdef (if the fallback isn't fast enough).
Two implications of this requirement:
1) There will not be SIMD in 7.8. I just don't have the time. In fact, what SIMD support is there already will have to be removed if we cannot live with LLVM-only SIMD primops.
2) If we also require interop between the LLVM back-end and the native codegen, then we cannot pass any SIMD vectors in registers---they all must be passed on the stack.
My plan, as discussed with Simon PJ, is to not support SIMD primops at all with the native codegen. If there is a strong feeling that this *is not* the way to go, the I need to know ASAP.
Geoff
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference. Geoff On 09/11/2013 07:59 PM, Johan Tibell wrote:
Do nothing different than you're doing for 7.8, we can sort it out later. Just put a comment on the primops saying they're LLVM-only. See e.g.
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
for an example how to add docs to primops.
I don't think we need interop between the native and the LLVM backends. We don't have that now do we (i.e. they use different calling conventions).
On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
On 09/11/2013 07:44 PM, Johan Tibell wrote: > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote: > > Do you mean we need a reasonable emulation of the SIMD primops for > > the native codegen? > > Yes. Reasonable in the sense that it computes the right result. I can > see that some code might still want to #ifdef (if the fallback isn't > fast enough).
Two implications of this requirement:
1) There will not be SIMD in 7.8. I just don't have the time. In fact, what SIMD support is there already will have to be removed if we cannot live with LLVM-only SIMD primops.
2) If we also require interop between the LLVM back-end and the native codegen, then we cannot pass any SIMD vectors in registers---they all must be passed on the stack.
My plan, as discussed with Simon PJ, is to not support SIMD primops at all with the native codegen. If there is a strong feeling that this *is not* the way to go, the I need to know ASAP.
Geoff
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable? On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote:
Do nothing different than you're doing for 7.8, we can sort it out later. Just put a comment on the primops saying they're LLVM-only. See e.g.
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
for an example how to add docs to primops.
I don't think we need interop between the native and the LLVM backends. We don't have that now do we (i.e. they use different calling conventions).
On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
On 09/11/2013 07:44 PM, Johan Tibell wrote: > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote: > > Do you mean we need a reasonable emulation of the SIMD primops
for
> > the native codegen? > > Yes. Reasonable in the sense that it computes the right result. I can > see that some code might still want to #ifdef (if the fallback
isn't
> fast enough).
Two implications of this requirement:
1) There will not be SIMD in 7.8. I just don't have the time. In
fact,
what SIMD support is there already will have to be removed if we cannot live with LLVM-only SIMD primops.
2) If we also require interop between the LLVM back-end and the
native
codegen, then we cannot pass any SIMD vectors in registers---they all must be passed on the stack.
My plan, as discussed with Simon PJ, is to not support SIMD primops
at
all with the native codegen. If there is a strong feeling that this *is not* the way to go, the I need to know ASAP.
Geoff
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.? In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions. Geoff On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > > https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 > > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
Geoff, a prosaic reason why there *might* be a fundamentally breaking change would be the following idea nathan howell suggested to me this afternoon: change the Sp and SPLim register so that the X86/x86_64 target can use the CPU's Push and (maybe) Pop instructions for the stack manipulations, rather than MOV and fam. see http://ghc.haskell.org/trac/ghc/ticket/8272 (which is just what i've said). Thats one change thats pretty simple but deep, but likely worth exploring. i'm saying any ABI change for GHC 7.10, would likely entail patching LLVM 3.4, because thats the only LLVM version likely to come out between now and whenever we get 7.10 out (assuming 7.10 lands within the next 8-12 months, which is reasonable since we've got noticeably more (amazing) people helping out lately). Thus, any change there entails either asking the llvm folks to support >1 GHC convention per architecture, or replace the current one! I'd rather do the latter than the former, when it comes to asking other people to maintain it :) (and llvm engineers do in fact help out maintaining that code) have you run a Nofib, or even benchmarks restricted to your multivector code, for the current calling convention (including the spilling AVX vectors to the stack thats the current plan i gather) VS passing in registers with an LLVM built using the patches i worked out ~ 2 months ago? it'd be really easy to build that custom llvm, then run the benchmarks! (i'm happy to help, and ultimately, benchmarks will reveal if its worth while or not! And if the main goal is for your talk, its still valid even if its not in the merge window over the next 4 days). I really think its not obvious what the "best" abi change would be! It really will require coming up with a list of variants, implementing them, and running nofib with each variant, which i lack the compute/human time resources to do this week. Modern hardware is complex enough that for something like an ABI change, the only healthy attitude can be "lets benchmark it!". i'd really like any change in calling convention to also improve perf on codes that aren't explicitly simd! (and a conservative simd only change, blocks/conflicts with that augmentation going forward, and not just for the stack pointer example i mention early) Not just scalar floats in simd registers , but perhaps also words/ints ! (though that latter bit might be pretty ambitious and subtle, i'll need to investigate that a bit to see how feasible it may be). SIMD has great support for ints/words, and any partial abi change on the llvm backend now would make it hard to support that later well (or at least, thats what it looks like to me). actually effectively using simd for scalar ints and words should be doable, but might force us to be a bit more thoughtful on how GHC internally distinguishes ints used for address arithmetic, vs ints used as data. (interestingly, i'm not sure if any current extent x86 calling convention does that!) That single change would make 7.10 require a completely different llvm and native code gen convention from our current one, plus touch all of the code gen on x86 architectures. basically: we're lucky that everyone builds haskell code from source, so ABI compat across GHC versions is a non issue. BUT, any ABI changes should be backed by benchmarks (at least when the change is performance motivated). Likewise, because we use LLVM as an external dep for the -fllvm backend, we really need to keep how their release cycle interacts with our release cycle, because people use haskell and ghc! which as many like to say, is both a boon and a pain ;). Having people hit ghc acting broken with an llvm that was "supported before" is risky support problem to deal with. having an LLVM head variant support a modified ABI, and then later needing to break it for 7.10 (for one of the possible exploratory reasons above) would lead to a support headache I don't wish on anyone. pardon the verbose answer, but thats my offhand take cheers -Carter On Wed, Sep 11, 2013 at 10:10 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if
we
> cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
that said it does occur to me that there is an alternative solution that may be acceptable for everyone! what about providing a pseudo compatible way called -fllvm-experimentalAVX (or something), and simply require that for it to be used, the user has an llvm Patched with the YMM simd in register fun call support? internally that could just be an llvm way that trips the logic that puts the first few AVX values in those YMM1-6 slots if they are the first args, so only the stack spilling logic needs be changed? (ie it wouldn't be tied to an llvm version, but rather this pseduo way flag) does that make sense? either way, i'd really like having avx even if its always spilled to stack at funcalls with standard LLVMs! cheers -carter On Thu, Sep 12, 2013 at 2:28 AM, Carter Schonwald < carter.schonwald@gmail.com> wrote:
Geoff,
a prosaic reason why there *might* be a fundamentally breaking change would be the following idea nathan howell suggested to me this afternoon: change the Sp and SPLim register so that the X86/x86_64 target can use the CPU's Push and (maybe) Pop instructions for the stack manipulations, rather than MOV and fam. see http://ghc.haskell.org/trac/ghc/ticket/8272(which is just what i've said). Thats one change thats pretty simple but deep, but likely worth exploring.
i'm saying any ABI change for GHC 7.10, would likely entail patching LLVM 3.4, because thats the only LLVM version likely to come out between now and whenever we get 7.10 out (assuming 7.10 lands within the next 8-12 months, which is reasonable since we've got noticeably more (amazing) people helping out lately). Thus, any change there entails either asking the llvm folks to support >1 GHC convention per architecture, or replace the current one! I'd rather do the latter than the former, when it comes to asking other people to maintain it :) (and llvm engineers do in fact help out maintaining that code)
have you run a Nofib, or even benchmarks restricted to your multivector code, for the current calling convention (including the spilling AVX vectors to the stack thats the current plan i gather) VS passing in registers with an LLVM built using the patches i worked out ~ 2 months ago? it'd be really easy to build that custom llvm, then run the benchmarks! (i'm happy to help, and ultimately, benchmarks will reveal if its worth while or not! And if the main goal is for your talk, its still valid even if its not in the merge window over the next 4 days).
I really think its not obvious what the "best" abi change would be! It really will require coming up with a list of variants, implementing them, and running nofib with each variant, which i lack the compute/human time resources to do this week. Modern hardware is complex enough that for something like an ABI change, the only healthy attitude can be "lets benchmark it!".
i'd really like any change in calling convention to also improve perf on codes that aren't explicitly simd! (and a conservative simd only change, blocks/conflicts with that augmentation going forward, and not just for the stack pointer example i mention early)
Not just scalar floats in simd registers , but perhaps also words/ints !
(though that latter bit might be pretty ambitious and subtle, i'll need to investigate that a bit to see how feasible it may be). SIMD has great support for ints/words, and any partial abi change on the llvm backend now would make it hard to support that later well (or at least, thats what it looks like to me). actually effectively using simd for scalar ints and words should be doable, but might force us to be a bit more thoughtful on how GHC internally distinguishes ints used for address arithmetic, vs ints used as data. (interestingly, i'm not sure if any current extent x86 calling convention does that!)
That single change would make 7.10 require a completely different llvm and native code gen convention from our current one, plus touch all of the code gen on x86 architectures.
basically: we're lucky that everyone builds haskell code from source, so ABI compat across GHC versions is a non issue. BUT, any ABI changes should be backed by benchmarks (at least when the change is performance motivated). Likewise, because we use LLVM as an external dep for the -fllvm backend, we really need to keep how their release cycle interacts with our release cycle, because people use haskell and ghc! which as many like to say, is both a boon and a pain ;).
Having people hit ghc acting broken with an llvm that was "supported before" is risky support problem to deal with. having an LLVM head variant support a modified ABI, and then later needing to break it for 7.10 (for one of the possible exploratory reasons above) would lead to a support headache I don't wish on anyone.
pardon the verbose answer, but thats my offhand take
cheers -Carter
On Wed, Sep 11, 2013 at 10:10 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if
we
> cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG. Did we discuss this before? I have vague memories, but don't remember what the outcome was. Cheers, Simon On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > > https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 > > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
We did discuss this, but you may not have been present. If LLVM-only primops show up in a non-LLVM codegen, a "sorry" error is reported telling the user that they need to compile with "-fllvm". Yes, this is not a fantastic solution. Options I see: 1) Live with the error message. 2) Remove all SIMD support until the NCG catches up. 3) Figure out a mechanism that avoids inlining any code containing LLVM-only primops when we're not using the LLVM back end. Maybe you can think of another solution? Geoff On 09/18/2013 02:54 PM, Simon Marlow wrote:
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG.
Did we discuss this before? I have vague memories, but don't remember what the outcome was.
Cheers, Simon
On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 > > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
On 18/09/13 20:01, Geoffrey Mainland wrote:
We did discuss this, but you may not have been present.
If LLVM-only primops show up in a non-LLVM codegen, a "sorry" error is reported telling the user that they need to compile with "-fllvm". Yes, this is not a fantastic solution. Options I see:
1) Live with the error message. 2) Remove all SIMD support until the NCG catches up. 3) Figure out a mechanism that avoids inlining any code containing LLVM-only primops when we're not using the LLVM back end.
Maybe you can think of another solution?
Those are the three unsatisfactory solutions that I know of. Even if we did (3), the user still wants to know when that is happening because they're getting less good code, so you'd want a warning. One thing we might try to do is automatically enable -fllvm when the compilation would otherwise fail. If LLVM isn't installed and the compilation still fails, it's no worse than failing to compile the module with the sorry error. Simon
Geoff
On 09/18/2013 02:54 PM, Simon Marlow wrote:
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG.
Did we discuss this before? I have vague memories, but don't remember what the outcome was.
Cheers, Simon
On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 > > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
I've some thoughts on how to have a better solution, but they are feasible only on a time scale suitable for 7.10, and not for 7.8. a hacky solution we could do for 7.8 perhaps is have a warning that works as follows: either a) throw a warning on functions that use the SIMD primops, if that function is being exported by a module, and that function isn't marked NOINLINE ? Theres probably a few subtleties to it, and this is just a naive idea b) somehow put both the -fllvm and -fasm core for inlineable functions in the .hi file? (this one prevents the most problems, but is probably the most complex work around we could do). its worth noting that the LLVM simd in 7.8, either way, won't support simd shuffles, which will seriously curtail its general utility, either way. -Carter On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com> wrote:
On 18/09/13 20:01, Geoffrey Mainland wrote:
We did discuss this, but you may not have been present.
If LLVM-only primops show up in a non-LLVM codegen, a "sorry" error is reported telling the user that they need to compile with "-fllvm". Yes, this is not a fantastic solution. Options I see:
1) Live with the error message. 2) Remove all SIMD support until the NCG catches up. 3) Figure out a mechanism that avoids inlining any code containing LLVM-only primops when we're not using the LLVM back end.
Maybe you can think of another solution?
Those are the three unsatisfactory solutions that I know of. Even if we did (3), the user still wants to know when that is happening because they're getting less good code, so you'd want a warning.
One thing we might try to do is automatically enable -fllvm when the compilation would otherwise fail. If LLVM isn't installed and the compilation still fails, it's no worse than failing to compile the module with the sorry error.
Simon
Geoff
On 09/18/2013 02:54 PM, Simon Marlow wrote:
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG.
Did we discuss this before? I have vague memories, but don't remember what the outcome was.
Cheers, Simon
On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/**blob/master/compiler/prelude/** primops.txt.pp#L181<https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181> > > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>**> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>**> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
On 09/18/2013 04:49 PM, Carter Schonwald wrote:
I've some thoughts on how to have a better solution, but they are feasible only on a time scale suitable for 7.10, and not for 7.8.
a hacky solution we could do for 7.8 perhaps is have a warning that works as follows:
either a) throw a warning on functions that use the SIMD primops, if that function is being exported by a module, and that function isn't marked NOINLINE ? Theres probably a few subtleties to it, and this is just a naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! b) somehow put both the -fllvm and -fasm core for inlineable functions in the .hi file? (this one prevents the most problems, but is probably the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8.
its worth noting that the LLVM simd in 7.8, either way, won't support simd shuffles, which will seriously curtail its general utility, either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com>> wrote:
On 18/09/13 20:01, Geoffrey Mainland wrote:
We did discuss this, but you may not have been present.
If LLVM-only primops show up in a non-LLVM codegen, a "sorry" error is reported telling the user that they need to compile with "-fllvm". Yes, this is not a fantastic solution. Options I see:
1) Live with the error message. 2) Remove all SIMD support until the NCG catches up. 3) Figure out a mechanism that avoids inlining any code containing LLVM-only primops when we're not using the LLVM back end.
Maybe you can think of another solution?
Those are the three unsatisfactory solutions that I know of. Even if we did (3), the user still wants to know when that is happening because they're getting less good code, so you'd want a warning.
One thing we might try to do is automatically enable -fllvm when the compilation would otherwise fail. If LLVM isn't installed and the compilation still fails, it's no worse than failing to compile the module with the sorry error.
Simon
Geoff
On 09/18/2013 02:54 PM, Simon Marlow wrote:
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG.
Did we discuss this before? I have vague memories, but don't remember what the outcome was.
Cheers, Simon
On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 > > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
yup, i hit a gap in what we can currently express in haskell types. We don't have a way of expressing static data! I actually put ticket on trac noting this. http://ghc.haskell.org/trac/ghc/ticket/8107 (note that when i was initially writing the ticket, i incorrectly thought the int# arg to ghc's prefetch was the locality level rather than a byte offset) Currently GHC has no way of expressing "this argument needs to be a static compile/codegen time constant" in surface haskell or core! This means we could at best provide a suite of special cased operations. (eg: we could provide the inter-lane shuffle for swapping halves of YMM registers, and the miniature analogue for XMM), but that would really be missing the point: being able to write complex algorithms that can work completely in registers! the vast majority of the simd shuffle operations have certain arguments that need to be compile time static values that are used in the actual code generation. The llvm data model doesn't express this constraint. This invariant failure was also hit internally recently via a bug in how GHC generated code for llvm's memcopy! http://ghc.haskell.org/trac/ghc/ticket/8131 If we could express llvm's shuffleVector<http://llvm.org/docs/LangRef.html#shufflevector-instruction>intrinsic in a type safe way, then we could express any of them. I would be over the moon if we could expose an operation like shuffleVector, but I dont' think GHC currently can express it in a type safe way that won't make LLVM vomit. I want simd shuffle, but i don't see how to give the fully general shuffle operations in type safe ways with ghc currently. We need to add support for some notion of static data first! If theres a way, i'm all for it, but I don't see such a way. I hope that answers your question. that seems to be a deep enough issue that theres no way to resolve it with simple engineering in the next few weeks. -Carter On Wed, Sep 18, 2013 at 9:41 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
On 09/18/2013 04:49 PM, Carter Schonwald wrote:
I've some thoughts on how to have a better solution, but they are feasible only on a time scale suitable for 7.10, and not for 7.8.
a hacky solution we could do for 7.8 perhaps is have a warning that works as follows:
either a) throw a warning on functions that use the SIMD primops, if that function is being exported by a module, and that function isn't marked NOINLINE ? Theres probably a few subtleties to it, and this is just a naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! b) somehow put both the -fllvm and -fasm core for inlineable functions in the .hi file? (this one prevents the most problems, but is probably the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8.
its worth noting that the LLVM simd in 7.8, either way, won't support simd shuffles, which will seriously curtail its general utility, either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com>> wrote:
On 18/09/13 20:01, Geoffrey Mainland wrote:
We did discuss this, but you may not have been present.
If LLVM-only primops show up in a non-LLVM codegen, a "sorry" error is reported telling the user that they need to compile with "-fllvm". Yes, this is not a fantastic solution. Options I see:
1) Live with the error message. 2) Remove all SIMD support until the NCG catches up. 3) Figure out a mechanism that avoids inlining any code containing LLVM-only primops when we're not using the LLVM back end.
Maybe you can think of another solution?
Those are the three unsatisfactory solutions that I know of. Even if we did (3), the user still wants to know when that is happening because they're getting less good code, so you'd want a warning.
One thing we might try to do is automatically enable -fllvm when the compilation would otherwise fail. If LLVM isn't installed and the compilation still fails, it's no worse than failing to compile the module with the sorry error.
Simon
Geoff
On 09/18/2013 02:54 PM, Simon Marlow wrote:
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG.
Did we discuss this before? I have vague memories, but don't remember what the outcome was.
Cheers, Simon
On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
tldr; we can't express / expose the LLVM shuffleVector intrinsic in a type safe way that will correctly interact with the static argument requirement for associated code generation. On Thu, Sep 19, 2013 at 12:40 AM, Carter Schonwald < carter.schonwald@gmail.com> wrote:
yup, i hit a gap in what we can currently express in haskell types. We don't have a way of expressing static data! I actually put ticket on trac noting this. http://ghc.haskell.org/trac/ghc/ticket/8107 (note that when i was initially writing the ticket, i incorrectly thought the int# arg to ghc's prefetch was the locality level rather than a byte offset)
Currently GHC has no way of expressing "this argument needs to be a static compile/codegen time constant" in surface haskell or core! This means we could at best provide a suite of special cased operations. (eg: we could provide the inter-lane shuffle for swapping halves of YMM registers, and the miniature analogue for XMM), but that would really be missing the point: being able to write complex algorithms that can work completely in registers!
the vast majority of the simd shuffle operations have certain arguments that need to be compile time static values that are used in the actual code generation. The llvm data model doesn't express this constraint. This invariant failure was also hit internally recently via a bug in how GHC generated code for llvm's memcopy! http://ghc.haskell.org/trac/ghc/ticket/8131
If we could express llvm's shuffleVector<http://llvm.org/docs/LangRef.html#shufflevector-instruction>intrinsic in a type safe way, then we could express any of them. I would be over the moon if we could expose an operation like shuffleVector, but I dont' think GHC currently can express it in a type safe way that won't make LLVM vomit.
I want simd shuffle, but i don't see how to give the fully general shuffle operations in type safe ways with ghc currently. We need to add support for some notion of static data first! If theres a way, i'm all for it, but I don't see such a way.
I hope that answers your question. that seems to be a deep enough issue that theres no way to resolve it with simple engineering in the next few weeks.
-Carter
On Wed, Sep 18, 2013 at 9:41 PM, Geoffrey Mainland <mainland@apeiron.net>wrote:
On 09/18/2013 04:49 PM, Carter Schonwald wrote:
I've some thoughts on how to have a better solution, but they are feasible only on a time scale suitable for 7.10, and not for 7.8.
a hacky solution we could do for 7.8 perhaps is have a warning that works as follows:
either a) throw a warning on functions that use the SIMD primops, if that function is being exported by a module, and that function isn't marked NOINLINE ? Theres probably a few subtleties to it, and this is just a naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! b) somehow put both the -fllvm and -fasm core for inlineable functions in the .hi file? (this one prevents the most problems, but is probably the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8.
its worth noting that the LLVM simd in 7.8, either way, won't support simd shuffles, which will seriously curtail its general utility, either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com>> wrote:
On 18/09/13 20:01, Geoffrey Mainland wrote:
We did discuss this, but you may not have been present.
If LLVM-only primops show up in a non-LLVM codegen, a "sorry" error is reported telling the user that they need to compile with "-fllvm". Yes, this is not a fantastic solution. Options I see:
1) Live with the error message. 2) Remove all SIMD support until the NCG catches up. 3) Figure out a mechanism that avoids inlining any code containing LLVM-only primops when we're not using the LLVM back end.
Maybe you can think of another solution?
Those are the three unsatisfactory solutions that I know of. Even if we did (3), the user still wants to know when that is happening because they're getting less good code, so you'd want a warning.
One thing we might try to do is automatically enable -fllvm when the compilation would otherwise fail. If LLVM isn't installed and the compilation still fails, it's no worse than failing to compile the module with the sorry error.
Simon
Geoff
On 09/18/2013 02:54 PM, Simon Marlow wrote:
This is slightly problematic. What if we have a wonderful SIMD-enabled vector library that we compile with -fllvm, and then use it in a program that isn't compiled with -fllvm, and some of the wonderful SIMD-enabled functions get inlined? Presumably we get a panic in the NCG.
Did we discuss this before? I have vague memories, but don't remember what the outcome was.
Cheers, Simon
On 12/09/13 03:10, Geoffrey Mainland wrote:
We support compiling some code with -fllvm and some not in the same executable. Otherwise how could users of the Haskell Platform link their -fllvm-compiled code with native-codegen-compiled libraries like base, etc.?
In other words, the LLVM and native back ends use the same calling convention. With my SIMD work, they still use the same calling conventions, but the native codegen can never generate code that uses SIMD instructions.
Geoff
On 09/11/2013 10:03 PM, Johan Tibell wrote:
OK. But that doesn't create a problem for the code we output with the LLVM backend, no? Or do we support compiling some code with -fllvm and some not in the same executable?
On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> wrote:
We definitely have interop between the native codegen and the LLVM back end now. Otherwise anyone who wanted to use the LLVM back end would have to build GHC themselves. Interop means that users can install the Haskell Platform and still use -fllvm when it makes a performance difference.
Geoff
On 09/11/2013 07:59 PM, Johan Tibell wrote: > Do nothing different than you're doing for 7.8, we can sort it out > later. Just put a comment on the primops saying they're LLVM-only. See > e.g. > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > for an example how to add docs to primops. > > I don't think we need interop between the native and the LLVM > backends. We don't have that now do we (i.e. they use different > calling conventions). > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > On 09/11/2013 07:44 PM, Johan Tibell wrote: > > On Wed, Sep 11, 2013 at 4:40 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > > Do you mean we need a reasonable emulation of the SIMD primops for > > > the native codegen? > > > > Yes. Reasonable in the sense that it computes the right result. > I can > > see that some code might still want to #ifdef (if the fallback isn't > > fast enough). > > Two implications of this requirement: > > 1) There will not be SIMD in 7.8. I just don't have the time. In fact, > what SIMD support is there already will have to be removed if we > cannot > live with LLVM-only SIMD primops. > > 2) If we also require interop between the LLVM back-end and the native > codegen, then we cannot pass any SIMD vectors in registers---they all > must be passed on the stack. > > My plan, as discussed with Simon PJ, is to not support SIMD primops at > all with the native codegen. If there is a strong feeling that > this *is > not* the way to go, the I need to know ASAP. > > Geoff > > >
If you pass a constant, unboxed value to a primop, I assume GHC won't ever bind the argument to a value. So although we have no way to enforce "static const argument" in the type system, if this is a valuable (and experts-only?) operation, I'm not sure it matters that much if the user gets an error at code-generation time complaining about non-const arguments. Another way to look at it: if we wait until someone enhances the type system to support the notion of static arguments, we will likely never have a bit shuffle primitive. The other option would be to fall back on a different implementation if we saw a non-constant argument. I think that would actually be worse than erroring out, but I'm sure others would disagree. Geoff On 09/19/2013 11:42 AM, Carter Schonwald wrote:
tldr; we can't express / expose the LLVM shuffleVector intrinsic in a type safe way that will correctly interact with the static argument requirement for associated code generation.
On Thu, Sep 19, 2013 at 12:40 AM, Carter Schonwald <carter.schonwald@gmail.com <mailto:carter.schonwald@gmail.com>> wrote:
yup, i hit a gap in what we can currently express in haskell types. We don't have a way of expressing static data! I actually put ticket on trac noting this. http://ghc.haskell.org/trac/ghc/ticket/8107 (note that when i was initially writing the ticket, i incorrectly thought the int# arg to ghc's prefetch was the locality level rather than a byte offset)
Currently GHC has no way of expressing "this argument needs to be a static compile/codegen time constant" in surface haskell or core! This means we could at best provide a suite of special cased operations. (eg: we could provide the inter-lane shuffle for swapping halves of YMM registers, and the miniature analogue for XMM), but that would really be missing the point: being able to write complex algorithms that can work completely in registers!
the vast majority of the simd shuffle operations have certain arguments that need to be compile time static values that are used in the actual code generation. The llvm data model doesn't express this constraint. This invariant failure was also hit internally recently via a bug in how GHC generated code for llvm's memcopy! http://ghc.haskell.org/trac/ghc/ticket/8131
If we could express llvm'sshuffleVector <http://llvm.org/docs/LangRef.html#shufflevector-instruction> intrinsic in a type safe way, then we could express any of them. I would be over the moon if we could expose an operation like shuffleVector, but I dont' think GHC currently can express it in a type safe way that won't make LLVM vomit.
I want simd shuffle, but i don't see how to give the fully general shuffle operations in type safe ways with ghc currently. We need to add support for some notion of static data first! If theres a way, i'm all for it, but I don't see such a way.
I hope that answers your question. that seems to be a deep enough issue that theres no way to resolve it with simple engineering in the next few weeks.
-Carter
On Wed, Sep 18, 2013 at 9:41 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
On 09/18/2013 04:49 PM, Carter Schonwald wrote: > I've some thoughts on how to have a better solution, but they are > feasible only on a time scale suitable for 7.10, and not for 7.8. > > a hacky solution we could do for 7.8 perhaps is have a warning that > works as follows: > > either > a) > throw a warning on functions that use the SIMD primops, if that > function is being exported by a module, and that function isn't marked > NOINLINE ? Theres probably a few subtleties to it, and this is just a > naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! > b) somehow put both the -fllvm and -fasm core for inlineable functions > in the .hi file? (this one prevents the most problems, but is probably > the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8. > > > its worth noting that the LLVM simd in 7.8, either way, won't support > simd shuffles, which will seriously curtail its general utility, > either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
> On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com> > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>> wrote: > > On 18/09/13 20:01, Geoffrey Mainland wrote: > > We did discuss this, but you may not have been present. > > If LLVM-only primops show up in a non-LLVM codegen, a "sorry" > error is > reported telling the user that they need to compile with > "-fllvm". Yes, > this is not a fantastic solution. Options I see: > > 1) Live with the error message. > 2) Remove all SIMD support until the NCG catches up. > 3) Figure out a mechanism that avoids inlining any code containing > LLVM-only primops when we're not using the LLVM back end. > > Maybe you can think of another solution? > > > Those are the three unsatisfactory solutions that I know of. Even > if we did (3), the user still wants to know when that is happening > because they're getting less good code, so you'd want a warning. > > One thing we might try to do is automatically enable -fllvm when > the compilation would otherwise fail. If LLVM isn't installed and > the compilation still fails, it's no worse than failing to compile > the module with the sorry error. > > Simon > > > > Geoff > > On 09/18/2013 02:54 PM, Simon Marlow wrote: > > This is slightly problematic. What if we have a wonderful > SIMD-enabled vector library that we compile with -fllvm, > and then use > it in a program that isn't compiled with -fllvm, and some > of the > wonderful SIMD-enabled functions get inlined? Presumably > we get a > panic in the NCG. > > Did we discuss this before? I have vague memories, but > don't remember > what the outcome was. > > Cheers, > Simon > > On 12/09/13 03:10, Geoffrey Mainland wrote: > > We support compiling some code with -fllvm and some > not in the same > executable. Otherwise how could users of the Haskell > Platform link their > -fllvm-compiled code with native-codegen-compiled > libraries like > base, etc.? > > In other words, the LLVM and native back ends use the > same calling > convention. With my SIMD work, they still use the same > calling > conventions, but the native codegen can never generate > code that uses > SIMD instructions. > > Geoff > > On 09/11/2013 10:03 PM, Johan Tibell wrote: > > OK. But that doesn't create a problem for the code > we output with the > LLVM backend, no? Or do we support compiling some > code with -fllvm and > some not in the same executable? > > > On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > We definitely have interop between the > native codegen and the LLVM > back > end now. Otherwise anyone who wanted to use > the LLVM back end > would have > to build GHC themselves. Interop means that > users can install the > Haskell Platform and still use -fllvm when > it makes a performance > difference. > > Geoff > > On 09/11/2013 07:59 PM, Johan Tibell wrote: > > Do nothing different than you're doing for > 7.8, we can sort > it out > > later. Just put a comment on the primops > saying they're > LLVM-only. See > > e.g. > > > > > > > > https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181 > > > > for an example how to add docs to primops. > > > > I don't think we need interop between the > native and the LLVM > > backends. We don't have that now do we > (i.e. they use different > > calling conventions). > > > > > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey > Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > On 09/11/2013 07:44 PM, Johan Tibell > wrote: > > > On Wed, Sep 11, 2013 at 4:40 PM, > Geoffrey Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > Do you mean we need a reasonable > emulation of the SIMD > primops for > > > > the native codegen? > > > > > > Yes. Reasonable in the sense that it > computes the right > result. > > I can > > > see that some code might still want > to #ifdef (if the > fallback isn't > > > fast enough). > > > > Two implications of this requirement: > > > > 1) There will not be SIMD in 7.8. I > just don't have the > time. In fact, > > what SIMD support is there already > will have to be > removed if we > > cannot > > live with LLVM-only SIMD primops. > > > > 2) If we also require interop between > the LLVM back-end and > the native > > codegen, then we cannot pass any SIMD > vectors in > registers---they all > > must be passed on the stack. > > > > My plan, as discussed with Simon PJ, > is to not support SIMD > primops at > > all with the native codegen. If there > is a strong feeling > that > > this *is > > not* the way to go, the I need to know > ASAP. > > > > Geoff > > > > > > > > > > > > >
I think Geoffrey's suggestion is workable, but I wouldn't like it so much. The difficulty is that if you aren't aware of it, it's possible to build up a large system that you discover is unworkable the first time you try to compile it. In that sense it's not too different from Template Haskell staging restrictions, which IIRC exist to deal with exactly this problem. As the necessity of compile-time constants has shown up at least twice, a more principled solution is worth investigating. In the meantime, a horrible hack would be something like: newtype CStatic v = CStatic ExpQ instance Num a => Num ( CStatic a) where fromInteger x = [| x |] and then the value could be spliced at the call site. Staging restrictions would ensure it's available at compile time. I guess the instance decl needs Lift too. Downsides are general hideous-ness, misleading error messages, and the necessity for compiling with template haskell. But you'd get an error if s value isn't a compile-time constant. (Please don't put this in ghc, but it's not so bad as a separate lib). John L. On Sep 19, 2013 3:44 PM, "Geoffrey Mainland" <mainland@apeiron.net> wrote:
If you pass a constant, unboxed value to a primop, I assume GHC won't ever bind the argument to a value. So although we have no way to enforce "static const argument" in the type system, if this is a valuable (and experts-only?) operation, I'm not sure it matters that much if the user gets an error at code-generation time complaining about non-const arguments.
Another way to look at it: if we wait until someone enhances the type system to support the notion of static arguments, we will likely never have a bit shuffle primitive.
The other option would be to fall back on a different implementation if we saw a non-constant argument. I think that would actually be worse than erroring out, but I'm sure others would disagree.
Geoff
On 09/19/2013 11:42 AM, Carter Schonwald wrote:
tldr; we can't express / expose the LLVM shuffleVector intrinsic in a type safe way that will correctly interact with the static argument requirement for associated code generation.
On Thu, Sep 19, 2013 at 12:40 AM, Carter Schonwald <carter.schonwald@gmail.com <mailto:carter.schonwald@gmail.com>> wrote:
yup, i hit a gap in what we can currently express in haskell types. We don't have a way of expressing static data! I actually put ticket on trac noting this. http://ghc.haskell.org/trac/ghc/ticket/8107 (note that when i was initially writing the ticket, i incorrectly thought the int# arg to ghc's prefetch was the locality level rather than a byte offset)
Currently GHC has no way of expressing "this argument needs to be a static compile/codegen time constant" in surface haskell or core! This means we could at best provide a suite of special cased operations. (eg: we could provide the inter-lane shuffle for swapping halves of YMM registers, and the miniature analogue for XMM), but that would really be missing the point: being able to write complex algorithms that can work completely in registers!
the vast majority of the simd shuffle operations have certain arguments that need to be compile time static values that are used in the actual code generation. The llvm data model doesn't express this constraint. This invariant failure was also hit internally recently via a bug in how GHC generated code for llvm's memcopy! http://ghc.haskell.org/trac/ghc/ticket/8131
If we could express llvm'sshuffleVector <http://llvm.org/docs/LangRef.html#shufflevector-instruction> intrinsic in a type safe way, then we could express any of them. I would be over the moon if we could expose an operation like shuffleVector, but I dont' think GHC currently can express it in a type safe way that won't make LLVM vomit.
I want simd shuffle, but i don't see how to give the fully general shuffle operations in type safe ways with ghc currently. We need to add support for some notion of static data first! If theres a way, i'm all for it, but I don't see such a way.
I hope that answers your question. that seems to be a deep enough issue that theres no way to resolve it with simple engineering in the next few weeks.
-Carter
On Wed, Sep 18, 2013 at 9:41 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
On 09/18/2013 04:49 PM, Carter Schonwald wrote: > I've some thoughts on how to have a better solution, but they are > feasible only on a time scale suitable for 7.10, and not for 7.8. > > a hacky solution we could do for 7.8 perhaps is have a warning that > works as follows: > > either > a) > throw a warning on functions that use the SIMD primops, if that > function is being exported by a module, and that function isn't marked > NOINLINE ? Theres probably a few subtleties to it, and this is just a > naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! > b) somehow put both the -fllvm and -fasm core for inlineable functions > in the .hi file? (this one prevents the most problems, but is probably > the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8. > > > its worth noting that the LLVM simd in 7.8, either way, won't support > simd shuffles, which will seriously curtail its general utility, > either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
> On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com> > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>> wrote: > > On 18/09/13 20:01, Geoffrey Mainland wrote: > > We did discuss this, but you may not have been present. > > If LLVM-only primops show up in a non-LLVM codegen, a "sorry" > error is > reported telling the user that they need to compile with > "-fllvm". Yes, > this is not a fantastic solution. Options I see: > > 1) Live with the error message. > 2) Remove all SIMD support until the NCG catches up. > 3) Figure out a mechanism that avoids inlining any code containing > LLVM-only primops when we're not using the LLVM back end. > > Maybe you can think of another solution? > > > Those are the three unsatisfactory solutions that I know of. Even > if we did (3), the user still wants to know when that is happening > because they're getting less good code, so you'd want a warning. > > One thing we might try to do is automatically enable -fllvm when > the compilation would otherwise fail. If LLVM isn't installed and > the compilation still fails, it's no worse than failing to compile > the module with the sorry error. > > Simon > > > > Geoff > > On 09/18/2013 02:54 PM, Simon Marlow wrote: > > This is slightly problematic. What if we have a wonderful > SIMD-enabled vector library that we compile with -fllvm, > and then use > it in a program that isn't compiled with -fllvm, and some > of the > wonderful SIMD-enabled functions get inlined? Presumably > we get a > panic in the NCG. > > Did we discuss this before? I have vague memories, but > don't remember > what the outcome was. > > Cheers, > Simon > > On 12/09/13 03:10, Geoffrey Mainland wrote: > > We support compiling some code with -fllvm and some > not in the same > executable. Otherwise how could users of the Haskell > Platform link their > -fllvm-compiled code with native-codegen-compiled > libraries like > base, etc.? > > In other words, the LLVM and native back ends use the > same calling > convention. With my SIMD work, they still use the same > calling > conventions, but the native codegen can never generate > code that uses > SIMD instructions. > > Geoff > > On 09/11/2013 10:03 PM, Johan Tibell wrote: > > OK. But that doesn't create a problem for the code > we output with the > LLVM backend, no? Or do we support compiling some > code with -fllvm and > some not in the same executable? > > > On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > We definitely have interop between the > native codegen and the LLVM > back > end now. Otherwise anyone who wanted to use > the LLVM back end > would have > to build GHC themselves. Interop means that > users can install the > Haskell Platform and still use -fllvm when > it makes a performance > difference. > > Geoff > > On 09/11/2013 07:59 PM, Johan Tibell wrote: > > Do nothing different than you're doing for > 7.8, we can sort > it out > > later. Just put a comment on the primops > saying they're > LLVM-only. See > > e.g. > > > > > > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > > > for an example how to add docs to primops. > > > > I don't think we need interop between the > native and the LLVM > > backends. We don't have that now do we > (i.e. they use different > > calling conventions). > > > > > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey > Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > On 09/11/2013 07:44 PM, Johan Tibell > wrote: > > > On Wed, Sep 11, 2013 at 4:40 PM, > Geoffrey Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > Do you mean we need a reasonable > emulation of the SIMD > primops for > > > > the native codegen? > > > > > > Yes. Reasonable in the sense that it > computes the right > result. > > I can > > > see that some code might still want > to #ifdef (if the > fallback isn't > > > fast enough). > > > > Two implications of this requirement: > > > > 1) There will not be SIMD in 7.8. I > just don't have the > time. In fact, > > what SIMD support is there already > will have to be > removed if we > > cannot > > live with LLVM-only SIMD primops. > > > > 2) If we also require interop between > the LLVM back-end and > the native > > codegen, then we cannot pass any SIMD > vectors in > registers---they all > > must be passed on the stack. > > > > My plan, as discussed with Simon PJ, > is to not support SIMD > primops at > > all with the native codegen. If there > is a strong feeling > that > > this *is > > not* the way to go, the I need to know > ASAP. > > > > Geoff > > > > > > > > > > > > >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs
@John, thats actually close to the sort of near term proposal i've been thinking of too! We could probably make it nicer by using the new typed template haskell (which geoff was/is also working on!). http://ghc.haskell.org/trac/ghc/blog/Template%20Haskell%20Proposal With typed template haskell, couldn't we have something like asStatic :: alpha -> TExp (Static alpha), where asStatic is the only way to introduce terms with a type (Static alpha)? (ie: we could only introduce static values that are closed, at Th time, which would also prevent us from construction a value of type (Static alpha) at runtime?) I think that would be enough to introduce the right compile time Static Data property. That would also probably capture the right notion of static for a number of other uses cases (I think. Probably would need a type class constraint on alpha, to rule out crazy things like Static (IORef Int) or the like ). we'd probably need to also have a fromStatic :: Static a -> a, too. But you're absolutely right, with a teeny bit of work, we could have at least a near term work around like that. Theres probably some subtlties i'm overlooking though On Fri, Sep 20, 2013 at 2:09 PM, John Lato <jwlato@gmail.com> wrote:
I think Geoffrey's suggestion is workable, but I wouldn't like it so much. The difficulty is that if you aren't aware of it, it's possible to build up a large system that you discover is unworkable the first time you try to compile it.
In that sense it's not too different from Template Haskell staging restrictions, which IIRC exist to deal with exactly this problem.
As the necessity of compile-time constants has shown up at least twice, a more principled solution is worth investigating.
In the meantime, a horrible hack would be something like:
newtype CStatic v = CStatic ExpQ instance Num a => Num ( CStatic a) where fromInteger x = [| x |]
and then the value could be spliced at the call site. Staging restrictions would ensure it's available at compile time. I guess the instance decl needs Lift too.
Downsides are general hideous-ness, misleading error messages, and the necessity for compiling with template haskell. But you'd get an error if s value isn't a compile-time constant. (Please don't put this in ghc, but it's not so bad as a separate lib).
John L. On Sep 19, 2013 3:44 PM, "Geoffrey Mainland" <mainland@apeiron.net> wrote:
If you pass a constant, unboxed value to a primop, I assume GHC won't ever bind the argument to a value. So although we have no way to enforce "static const argument" in the type system, if this is a valuable (and experts-only?) operation, I'm not sure it matters that much if the user gets an error at code-generation time complaining about non-const arguments.
Another way to look at it: if we wait until someone enhances the type system to support the notion of static arguments, we will likely never have a bit shuffle primitive.
The other option would be to fall back on a different implementation if we saw a non-constant argument. I think that would actually be worse than erroring out, but I'm sure others would disagree.
Geoff
On 09/19/2013 11:42 AM, Carter Schonwald wrote:
tldr; we can't express / expose the LLVM shuffleVector intrinsic in a type safe way that will correctly interact with the static argument requirement for associated code generation.
On Thu, Sep 19, 2013 at 12:40 AM, Carter Schonwald <carter.schonwald@gmail.com <mailto:carter.schonwald@gmail.com>> wrote:
yup, i hit a gap in what we can currently express in haskell types. We don't have a way of expressing static data! I actually put ticket on trac noting this. http://ghc.haskell.org/trac/ghc/ticket/8107 (note that when i was initially writing the ticket, i incorrectly thought the int# arg to ghc's prefetch was the locality level rather than a byte offset)
Currently GHC has no way of expressing "this argument needs to be a static compile/codegen time constant" in surface haskell or core! This means we could at best provide a suite of special cased operations. (eg: we could provide the inter-lane shuffle for swapping halves of YMM registers, and the miniature analogue for XMM), but that would really be missing the point: being able to write complex algorithms that can work completely in registers!
the vast majority of the simd shuffle operations have certain arguments that need to be compile time static values that are used in the actual code generation. The llvm data model doesn't express this constraint. This invariant failure was also hit internally recently via a bug in how GHC generated code for llvm's memcopy! http://ghc.haskell.org/trac/ghc/ticket/8131
If we could express llvm'sshuffleVector <http://llvm.org/docs/LangRef.html#shufflevector-instruction> intrinsic in a type safe way, then we could express any of them. I would be over the moon if we could expose an operation like shuffleVector, but I dont' think GHC currently can express it in a type safe way that won't make LLVM vomit.
I want simd shuffle, but i don't see how to give the fully general shuffle operations in type safe ways with ghc currently. We need to add support for some notion of static data first! If theres a way, i'm all for it, but I don't see such a way.
I hope that answers your question. that seems to be a deep enough issue that theres no way to resolve it with simple engineering in the next few weeks.
-Carter
On Wed, Sep 18, 2013 at 9:41 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
On 09/18/2013 04:49 PM, Carter Schonwald wrote: > I've some thoughts on how to have a better solution, but they are > feasible only on a time scale suitable for 7.10, and not for 7.8. > > a hacky solution we could do for 7.8 perhaps is have a warning that > works as follows: > > either > a) > throw a warning on functions that use the SIMD primops, if that > function is being exported by a module, and that function isn't marked > NOINLINE ? Theres probably a few subtleties to it, and this is just a > naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! > b) somehow put both the -fllvm and -fasm core for inlineable functions > in the .hi file? (this one prevents the most problems, but is probably > the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8. > > > its worth noting that the LLVM simd in 7.8, either way, won't support > simd shuffles, which will seriously curtail its general utility, > either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
> On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com> > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>> wrote: > > On 18/09/13 20:01, Geoffrey Mainland wrote: > > We did discuss this, but you may not have been present. > > If LLVM-only primops show up in a non-LLVM codegen, a "sorry" > error is > reported telling the user that they need to compile with > "-fllvm". Yes, > this is not a fantastic solution. Options I see: > > 1) Live with the error message. > 2) Remove all SIMD support until the NCG catches up. > 3) Figure out a mechanism that avoids inlining any code containing > LLVM-only primops when we're not using the LLVM back end. > > Maybe you can think of another solution? > > > Those are the three unsatisfactory solutions that I know of. Even > if we did (3), the user still wants to know when that is happening > because they're getting less good code, so you'd want a warning. > > One thing we might try to do is automatically enable -fllvm when > the compilation would otherwise fail. If LLVM isn't installed and > the compilation still fails, it's no worse than failing to compile > the module with the sorry error. > > Simon > > > > Geoff > > On 09/18/2013 02:54 PM, Simon Marlow wrote: > > This is slightly problematic. What if we have a wonderful > SIMD-enabled vector library that we compile with -fllvm, > and then use > it in a program that isn't compiled with -fllvm, and some > of the > wonderful SIMD-enabled functions get inlined? Presumably > we get a > panic in the NCG. > > Did we discuss this before? I have vague memories, but > don't remember > what the outcome was. > > Cheers, > Simon > > On 12/09/13 03:10, Geoffrey Mainland wrote: > > We support compiling some code with -fllvm and some > not in the same > executable. Otherwise how could users of the Haskell > Platform link their > -fllvm-compiled code with native-codegen-compiled > libraries like > base, etc.? > > In other words, the LLVM and native back ends use the > same calling > convention. With my SIMD work, they still use the same > calling > conventions, but the native codegen can never generate > code that uses > SIMD instructions. > > Geoff > > On 09/11/2013 10:03 PM, Johan Tibell wrote: > > OK. But that doesn't create a problem for the code > we output with the > LLVM backend, no? Or do we support compiling some > code with -fllvm and > some not in the same executable? > > > On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > We definitely have interop between the > native codegen and the LLVM > back > end now. Otherwise anyone who wanted to use > the LLVM back end > would have > to build GHC themselves. Interop means that > users can install the > Haskell Platform and still use -fllvm when > it makes a performance > difference. > > Geoff > > On 09/11/2013 07:59 PM, Johan Tibell wrote: > > Do nothing different than you're doing for > 7.8, we can sort > it out > > later. Just put a comment on the primops > saying they're > LLVM-only. See > > e.g. > > > > > > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > > > for an example how to add docs to primops. > > > > I don't think we need interop between the > native and the LLVM > > backends. We don't have that now do we > (i.e. they use different > > calling conventions). > > > > > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey > Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > On 09/11/2013 07:44 PM, Johan Tibell > wrote: > > > On Wed, Sep 11, 2013 at 4:40 PM, > Geoffrey Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > Do you mean we need a reasonable > emulation of the SIMD > primops for > > > > the native codegen? > > > > > > Yes. Reasonable in the sense that it > computes the right > result. > > I can > > > see that some code might still want > to #ifdef (if the > fallback isn't > > > fast enough). > > > > Two implications of this requirement: > > > > 1) There will not be SIMD in 7.8. I > just don't have the > time. In fact, > > what SIMD support is there already > will have to be > removed if we > > cannot > > live with LLVM-only SIMD primops. > > > > 2) If we also require interop between > the LLVM back-end and > the native > > codegen, then we cannot pass any SIMD > vectors in > registers---they all > > must be passed on the stack. > > > > My plan, as discussed with Simon PJ, > is to not support SIMD > primops at > > all with the native codegen. If there > is a strong feeling > that > > this *is > > not* the way to go, the I need to know > ASAP. > > > > Geoff > > > > > > > > > > > > >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs
@carter you're completely correct, typed template haskell would be very nice for this. I think something like asStatic would be fine. It would be slightly annoying to not be able to use numeric literals, but it seems like a good first step at any rate. It would probably be possible to generate a Static value at runtime via the ghc api. But perhaps not, I haven't played with the typed template haskell enough to know. As to constructions like Static (IORef Int), that seems to capture the semantics of a global IORef, maybe it could be useful for that sort of application? On Sep 20, 2013 3:19 PM, "Carter Schonwald" <carter.schonwald@gmail.com> wrote:
@John, thats actually close to the sort of near term proposal i've been thinking of too!
We could probably make it nicer by using the new typed template haskell (which geoff was/is also working on!). http://ghc.haskell.org/trac/ghc/blog/Template%20Haskell%20Proposal
With typed template haskell, couldn't we have something like
asStatic :: alpha -> TExp (Static alpha),
where asStatic is the only way to introduce terms with a type (Static alpha)? (ie: we could only introduce static values that are closed, at Th time, which would also prevent us from construction a value of type (Static alpha) at runtime?)
I think that would be enough to introduce the right compile time Static Data property. That would also probably capture the right notion of static for a number of other uses cases (I think. Probably would need a type class constraint on alpha, to rule out crazy things like Static (IORef Int) or the like ).
we'd probably need to also have a fromStatic :: Static a -> a, too.
But you're absolutely right, with a teeny bit of work, we could have at least a near term work around like that. Theres probably some subtlties i'm overlooking though
On Fri, Sep 20, 2013 at 2:09 PM, John Lato <jwlato@gmail.com> wrote:
I think Geoffrey's suggestion is workable, but I wouldn't like it so much. The difficulty is that if you aren't aware of it, it's possible to build up a large system that you discover is unworkable the first time you try to compile it.
In that sense it's not too different from Template Haskell staging restrictions, which IIRC exist to deal with exactly this problem.
As the necessity of compile-time constants has shown up at least twice, a more principled solution is worth investigating.
In the meantime, a horrible hack would be something like:
newtype CStatic v = CStatic ExpQ instance Num a => Num ( CStatic a) where fromInteger x = [| x |]
and then the value could be spliced at the call site. Staging restrictions would ensure it's available at compile time. I guess the instance decl needs Lift too.
Downsides are general hideous-ness, misleading error messages, and the necessity for compiling with template haskell. But you'd get an error if s value isn't a compile-time constant. (Please don't put this in ghc, but it's not so bad as a separate lib).
John L. On Sep 19, 2013 3:44 PM, "Geoffrey Mainland" <mainland@apeiron.net> wrote:
If you pass a constant, unboxed value to a primop, I assume GHC won't ever bind the argument to a value. So although we have no way to enforce "static const argument" in the type system, if this is a valuable (and experts-only?) operation, I'm not sure it matters that much if the user gets an error at code-generation time complaining about non-const arguments.
Another way to look at it: if we wait until someone enhances the type system to support the notion of static arguments, we will likely never have a bit shuffle primitive.
The other option would be to fall back on a different implementation if we saw a non-constant argument. I think that would actually be worse than erroring out, but I'm sure others would disagree.
Geoff
On 09/19/2013 11:42 AM, Carter Schonwald wrote:
tldr; we can't express / expose the LLVM shuffleVector intrinsic in a type safe way that will correctly interact with the static argument requirement for associated code generation.
On Thu, Sep 19, 2013 at 12:40 AM, Carter Schonwald <carter.schonwald@gmail.com <mailto:carter.schonwald@gmail.com>> wrote:
yup, i hit a gap in what we can currently express in haskell types. We don't have a way of expressing static data! I actually put ticket on trac noting this. http://ghc.haskell.org/trac/ghc/ticket/8107 (note that when i was initially writing the ticket, i incorrectly thought the int# arg to ghc's prefetch was the locality level rather than a byte offset)
Currently GHC has no way of expressing "this argument needs to be a static compile/codegen time constant" in surface haskell or core! This means we could at best provide a suite of special cased operations. (eg: we could provide the inter-lane shuffle for swapping halves of YMM registers, and the miniature analogue for XMM), but that would really be missing the point: being able to write complex algorithms that can work completely in registers!
the vast majority of the simd shuffle operations have certain arguments that need to be compile time static values that are used in the actual code generation. The llvm data model doesn't express this constraint. This invariant failure was also hit internally recently via a bug in how GHC generated code for llvm's memcopy! http://ghc.haskell.org/trac/ghc/ticket/8131
If we could express llvm'sshuffleVector <http://llvm.org/docs/LangRef.html#shufflevector-instruction> intrinsic in a type safe way, then we could express any of them. I would be over the moon if we could expose an operation like shuffleVector, but I dont' think GHC currently can express it in a type safe way that won't make LLVM vomit.
I want simd shuffle, but i don't see how to give the fully general shuffle operations in type safe ways with ghc currently. We need to add support for some notion of static data first! If theres a way, i'm all for it, but I don't see such a way.
I hope that answers your question. that seems to be a deep enough issue that theres no way to resolve it with simple engineering in the next few weeks.
-Carter
On Wed, Sep 18, 2013 at 9:41 PM, Geoffrey Mainland <mainland@apeiron.net <mailto:mainland@apeiron.net>> wrote:
On 09/18/2013 04:49 PM, Carter Schonwald wrote: > I've some thoughts on how to have a better solution, but they are > feasible only on a time scale suitable for 7.10, and not for 7.8. > > a hacky solution we could do for 7.8 perhaps is have a warning that > works as follows: > > either > a) > throw a warning on functions that use the SIMD primops, if that > function is being exported by a module, and that function isn't marked > NOINLINE ? Theres probably a few subtleties to it, and this is just a > naive idea That wouldn't inform the consumers of a module. And for a library like vector, we definitely want to export unfoldings for code that contains SIMD primops. That's the only way to get good code out of the library! > b) somehow put both the -fllvm and -fasm core for inlineable functions > in the .hi file? (this one prevents the most problems, but is probably > the most complex work around we could do). The problem being that there *is* no -fasm code...because the NCG doesn't support SIMD operations. Unless we added a mechanism to have two completely different, but simultaneous, definitions for a function, one for -fasm and one for -fllvm. But that would be a lot of work and couldn't be done for 7.8. > > > its worth noting that the LLVM simd in 7.8, either way, won't support > simd shuffles, which will seriously curtail its general utility, > either way.
You told me you would send me example use cases, type signatures, etc. Did I miss an email? If this is very important to you, was there a particular difficulty you had implementing these primops?
> On Wed, Sep 18, 2013 at 4:22 PM, Simon Marlow <marlowsd@gmail.com <mailto:marlowsd@gmail.com> > <mailto:marlowsd@gmail.com <mailto:marlowsd@gmail.com>>> wrote: > > On 18/09/13 20:01, Geoffrey Mainland wrote: > > We did discuss this, but you may not have been present. > > If LLVM-only primops show up in a non-LLVM codegen, a "sorry" > error is > reported telling the user that they need to compile with > "-fllvm". Yes, > this is not a fantastic solution. Options I see: > > 1) Live with the error message. > 2) Remove all SIMD support until the NCG catches up. > 3) Figure out a mechanism that avoids inlining any code containing > LLVM-only primops when we're not using the LLVM back end. > > Maybe you can think of another solution? > > > Those are the three unsatisfactory solutions that I know of. Even > if we did (3), the user still wants to know when that is happening > because they're getting less good code, so you'd want a warning. > > One thing we might try to do is automatically enable -fllvm when > the compilation would otherwise fail. If LLVM isn't installed and > the compilation still fails, it's no worse than failing to compile > the module with the sorry error. > > Simon > > > > Geoff > > On 09/18/2013 02:54 PM, Simon Marlow wrote: > > This is slightly problematic. What if we have a wonderful > SIMD-enabled vector library that we compile with -fllvm, > and then use > it in a program that isn't compiled with -fllvm, and some > of the > wonderful SIMD-enabled functions get inlined? Presumably > we get a > panic in the NCG. > > Did we discuss this before? I have vague memories, but > don't remember > what the outcome was. > > Cheers, > Simon > > On 12/09/13 03:10, Geoffrey Mainland wrote: > > We support compiling some code with -fllvm and some > not in the same > executable. Otherwise how could users of the Haskell > Platform link their > -fllvm-compiled code with native-codegen-compiled > libraries like > base, etc.? > > In other words, the LLVM and native back ends use the > same calling > convention. With my SIMD work, they still use the same > calling > conventions, but the native codegen can never generate > code that uses > SIMD instructions. > > Geoff > > On 09/11/2013 10:03 PM, Johan Tibell wrote: > > OK. But that doesn't create a problem for the code > we output with the > LLVM backend, no? Or do we support compiling some > code with -fllvm and > some not in the same executable? > > > On Wed, Sep 11, 2013 at 6:56 PM, Geoffrey Mainland > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>> wrote: > > We definitely have interop between the > native codegen and the LLVM > back > end now. Otherwise anyone who wanted to use > the LLVM back end > would have > to build GHC themselves. Interop means that > users can install the > Haskell Platform and still use -fllvm when > it makes a performance > difference. > > Geoff > > On 09/11/2013 07:59 PM, Johan Tibell wrote: > > Do nothing different than you're doing for > 7.8, we can sort > it out > > later. Just put a comment on the primops > saying they're > LLVM-only. See > > e.g. > > > > > > > >
https://github.com/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp#L181
> > > > for an example how to add docs to primops. > > > > I don't think we need interop between the > native and the LLVM > > backends. We don't have that now do we > (i.e. they use different > > calling conventions). > > > > > > > > On Wed, Sep 11, 2013 at 4:51 PM, Geoffrey > Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > On 09/11/2013 07:44 PM, Johan Tibell > wrote: > > > On Wed, Sep 11, 2013 at 4:40 PM, > Geoffrey Mainland > > <mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net> > <mailto:mainland@apeiron.net <mailto:mainland@apeiron.net>>>>> > wrote: > > > > Do you mean we need a reasonable > emulation of the SIMD > primops for > > > > the native codegen? > > > > > > Yes. Reasonable in the sense that it > computes the right > result. > > I can > > > see that some code might still want > to #ifdef (if the > fallback isn't > > > fast enough). > > > > Two implications of this requirement: > > > > 1) There will not be SIMD in 7.8. I > just don't have the > time. In fact, > > what SIMD support is there already > will have to be > removed if we > > cannot > > live with LLVM-only SIMD primops. > > > > 2) If we also require interop between > the LLVM back-end and > the native > > codegen, then we cannot pass any SIMD > vectors in > registers---they all > > must be passed on the stack. > > > > My plan, as discussed with Simon PJ, > is to not support SIMD > primops at > > all with the native codegen. If there > is a strong feeling > that > > this *is > > not* the way to go, the I need to know > ASAP. > > > > Geoff > > > > > > > > > > > > >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs
participants (5)
-
Carter Schonwald -
Geoffrey Mainland -
Johan Tibell -
John Lato -
Simon Marlow