Simon

> |  Could you explain the need of further info-tables for 'inner'
> |  proc-points (those, which are not the entry-block of a function) to
> |  me, please?
> 
> The main purpose of inner info tables is this.  Given (case e of blah) we 
> push a return address (for 'blah') on the stack and evaluate 'e'.  During 
> evaluation of 'e', garbage collection may take place.  So the garbage 
> collector needs to walk the stack to follow live pointers.  Who knows what 
> pointers are live?  Answer: the code for 'blah' clearly knows what pointers 
> are alive in the current stack frame, because it is going to access them.  So 
> the return address gets an info table that makes that implicit knowledge 
> explicit, as a bitmap describing the liveness/pointer-hood of the stack frame.
> 
> Addresses that are only jumped to don’t need info tables.
> 
> It would be great if, as you learn about this stuff, you could add to the 
> Commentary
> https://ghc.haskell.org/trac/ghc/wiki/Commentary
> to capture what you have learned.

Thank you very much! In cases I find the current description imprecise
or incomplete I can add what I've learned to the Commentary of course.

> |  The documentation states, that proc-point splitting is only required
> |  by the LLVM backend (see [2]). Does the cmm-pipeline perform proc-
> |  point splitting even when using the native code generator?
> 
> I'm not certain, but I don't think so.
> 
> |  As stated above, the major problem of LLVM seems to be inferring
> |  control flow when it comes to call proc-points. As it's hard to avoid
> |  proc-point splitting, we leave the cmm-pipeline 'as-is'. We modify the
> 
> I regard the whole proc-point thing as a major wart.  I think we should work 
> hard to eliminate it.  So: another line of thought might be: how could we 
> influence LLVM so that we didn't need proc-point splitting?

I totally agree with you here. However, determining how LLVM needs to be
influenced to eliminate proc-point splitting is a thing I won't be
capable of doing mid term because of my current knowledge and lack of time.

> |  To make control flow more apparent to LLVM, they came up with the
> |  following idea. Remark before showing the idea: I know that it greatly
> 
> I'm sorry to say that I didn't really understand the idea.  Maybe someone 
> else did?  David Terei?

My apologies for being imprecise. I hope to find the time to
work out a little demonstration during the upcoming holidays. I'm
currently fully occupied by university because of upcoming exams this week.

> If you are seriously about investing effort in the back end, I'd be happy to 
> help; in that case a Skype call is probably the best way.

That is a great idea. Due to the above mentioned time constraints I
propose that we follow up in January.

Regards,

David





> Simon
> 
> |  interferes with CPS. It leaves parts of the continuation-handling to
> |  the implicit LLVM call-stack. Further, this does not solve the problem
> |  of proc-point splitting at all. It is more a workaround than a
> |  solution.
> |  But it would greatly increase LLVM's possibilities to optimize code
> |  later on. That's why I found this idea worth mentioning. Especially
> |  because after reading your answer, Ben, I'm somewhat convinced that
> |  solving the problem of proc-point splitting is nearly impossible with
> |  the capabilities of LLVM IR available at the moment. Now back to the
> |  idea.
> |  
> |  As stated above, the major problem of LLVM seems to be inferring
> |  control flow when it comes to call proc-points. As it's hard to avoid
> |  proc-point splitting, we leave the cmm-pipeline 'as-is'. We modify the
> |  code, llvmGen produces when it comes to call proc-points instead. All
> |  other types of proc-points remain unchanged.
> |  
> |  Initial situation in pseudo cmm:
> |  
> |  foo() {
> |  ...
> |  call bar() returns to cont // bar defined externally
> |  
> |  cont:
> |  ...
> |  }
> |  
> |  After proc-point splitting, this is converted into LLVM IR similar to
> |  the following:
> |  
> |  @foo() {
> |  ...
> |  store @cont(), %Sp ; push continuation on the stack tail call @bar() ;
> |  @bar defined externally }
> |  
> |  @cont() {
> |  ...
> |  }
> |  
> |  To fix the above issue, we introduce a method, which restores the
> |  pointers Sp, Hp and the register R1 (among everything else, what has
> |  to be restored) and 'fakes' the continuation. Note, that '@restore'
> |  returns without calling into the continuation. This way, the call into
> |  the continuation can be made direct. The above code would be
> |  transformed into something similar to the following:
> |  
> |  @foo() {
> |  ...
> |  store @restore(), %Sp ; 'fake' continuation call @bar() ; br label
> |  restore
> |  
> |  restore:
> |  %Sp = load (getelementptr @environment 0, 0) ; restore what has to be
> |  ... ; restored tail call @cont() }
> |  
> |  @cont() {
> |  ...
> |  }
> |  
> |  @restore(%Sp, %Hp, %R1, ...) {
> |  store %Sp, (getelementptr @environment 0, 0) ; store everything into
> |  ... ; global variable ret void }
> |  
> |  @environment ; structure of type similar to {i64*, i64*, i64*, i64,
> |  i64, ..}
> |  
> |  As an alternative, the above transformation could be done by a LLVM
> |  pass. llvmGen could then annotate the continuation of calls call cite.
> |  This would greatly simplify the detection of the correct continuation.
> |  
> |  What do you think about this idea? Especially when thinking about the
> |  interference with CPS?
> |  
> |  Regards,
> |  
> |  David
> |  
> |  
> |  
> |  
> |  [1]
> |  https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/GeneratedCod
> |  e#Importantconceptsinthemachine
> |  
> |  [2]
> |  https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/CodeGen#Seco
> |  ndstage:theCmmpipeline
> |  
> |  
> |  
> |  
> |  On 11/21/2015 12:00 AM, Ben Gamari wrote:
> |  > Simon Peyton Jones <[email protected]> writes:
> |  >
> |  >> David
> |  >>
> |  >> All this stuff is terribly paged-out for me. But I'd love someone
> |  to
> |  >> pay attention to some of this back-end stuff, so if you'd like to
> |  >> work there, I'd like to help you.
> |  >>
> |  >> David Terei was also thinking of getting rid of proc point
> |  splitting
> |  >> for LLVM (see attached email and the notes attached to it)
> |  >>
> |  >> Simon Marlow also was thinking about this; see his attached email.
> |  >>
> |  >> The main *reason* for establishing a proc-point is so that, when
> |  >> generating C code (which we don't do any more) you can take its
> |  >> address. E.g.
> |  >>
> |  >> foo() { ... Push &bar onto the stack (effectively a return address)
> |  >>   Jump to thingumpy }
> |  >>
> |  >> bar() { ... }
> |  >>
> |  >> Really bar is part of foo, but we have make it a separate top level
> |  >> thing so that we can take the address of bar and push it on the
> |  stack.
> |  >>
> |  >> The trouble is that if there is a label inside bar that foo wants
> |  to
> |  >> jump to (i.e. without pushing &bar etc) then we have to make that
> |  >> label too into a proc-point, so that both foo and bar can see it.
> |  >> Urgh.
> |  >>
> |  >> In LLVM this probably is not true; presumably you can take the
> |  >> address of any label?
> |  >>
> |  > This is true. While labels themselves have function-local scope in
> |  > LLVM, there is an expression, `blockaddress`, which allows you to
> |  take
> |  > an address to a label in another function [1]. That being said, in
> |  > reading through the documentation it's not at all clear to me that
> |  it
> |  > would be safe to jump to such an address. In fact, given that the
> |  > instruction that this expression is supposed to be used with,
> |  > `indirectbr`, can only be used for local blocks, I suspect it is
> |  not.
> |  > More information about this feature can be found here [2].
> |  >
> |  > The jump issue aside, I don't know how you would deal with
> |  > tables-next-to-code. The prefix data support that currently
> |  available
> |  > in LLVM is attached to functions and I unfortunately don't see that
> |  > changing any time soon.
> |  >
> |  > Ultimately it seems that trying to refer to labels defined in other
> |  > functions is using LLVM against the way it was intended. One
> |  > alternative would be to teach llvmGen to merge mutually recusive
> |  > top-level functions into a single LLVM function during code
> |  > generation. Otherwise I'm afraid you are stuck with either the
> |  status
> |  > quo or attempting to improve on LLVM's own cross-procedure
> |  optimization ability.
> |  >
> |  > That being said, it sounds as though eliminating proc-point
> |  splitting
> |  > would make for quite a nice project in the native code generator.
> |  >
> |  > Cheers,
> |  >
> |  > - Ben
> |  >
> |  >
> |  > [1]
> |  >
> |  https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fllvm.o
> |  > rg%2fdocs%2fLangRef.html%23addresses-of-basic-
> |  blocks&data=01%7c01%7csi
> |  >
> |  monpj%40064d.mgd.microsoft.com%7c7fdbfda0b4514a098c4d08d2f74448f1%7c72
> |  >
> |  f988bf86f141af91ab2d7cd011db47%7c1&sdata=nKVLgmZezUdEYL%2fma1exMMPLbcT
> |  > RkaE1JrvVaR1EesY%3d [2]
> |  >
> |  https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fblog.l
> |  > lvm.org%2f2010%2f01%2faddress-of-label-and-indirect-
> |  branches.html&data
> |  >
> |  =01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c7fdbfda0b4514a098c4d08d2
> |  >
> |  f74448f1%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=BTMdZESwYS4tZa5W
> |  > sOAqyFutoI5xNNFDe0b%2bdKC3ODs%3d [3]
> |  >
> |  https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fllvm.o
> |  > rg%2fdocs%2fLangRef.html%23prefix-
> |  data&data=01%7c01%7csimonpj%40064d.m
> |  >
> |  gd.microsoft.com%7c7fdbfda0b4514a098c4d08d2f74448f1%7c72f988bf86f141af
> |  >
> |  91ab2d7cd011db47%7c1&sdata=rdo4ZLjjE%2bWxNykVL%2bSuToWioY6nzQpflSk296E
> |  > 8W70%3d
> |  >
> 


_______________________________________________
ghc-devs mailing list
[email protected]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Reply via email to