
David
| 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.
| 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?
| 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?
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.
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