Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local Variables #584

Merged
merged 5 commits into from
Sep 13, 2024
Merged

Local Variables #584

merged 5 commits into from
Sep 13, 2024

Conversation

serkm
Copy link
Contributor

@serkm serkm commented Sep 10, 2024

Allocate local variables directly on the stack, with a special stack frame

%stackPointerPointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
%basePointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 1

%stackPointer = load %StackPointer, ptr %stackPointerPointer
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, we now try to use the convention Foo_pointer. So this will be stackPointer_pointer

@b-studios
Copy link
Collaborator

Great job! Do you have results on running benchmarks on this?

@serkm
Copy link
Contributor Author

serkm commented Sep 13, 2024

I ran benchmarks and this seems to be slower in most cases.
Probably because we write 3 additional pointers to the stack for each variable.
Maybe this could be mitigated by allocating the variable in the next frame to be pushed, by adding a special case for Var(..., PushFrame(...))

@b-studios
Copy link
Collaborator

b-studios commented Sep 13, 2024

Thanks for running the benchmarks. Your analysis makes perfect sense! I think there are several things that we could do:

  • flatten multiple variables into one (that is, var (x, y) = (1, 2); ...)
  • somehow put the erasers and sharers relative to the return address so that we only store that one (1 store instead of 3)
  • dynamically detect your special case (and my first special case here) and flatten at runtime (way too complicated, I guess).

What "normal" people do is to push a stackframe for every function. The stackframe has a "shape" and we thus know how many locals there will be at most (that means, we only have one eraser / sharer per frame-shape).

Now in our LLVM backend we do not push every function frame, but only val frames for non-tail calls. However, we could still do the same and statically allocate local mutable variables for each val frame. This might:

a) lead to longer lifetimes for some mutable variables
b) confuse LLVM in performing optimizations

@phischu
Copy link
Collaborator

phischu commented Sep 13, 2024

Could you rebase onto current master? I can not reproduce the bad benchmarks, we should discuss offline.

Copy link
Collaborator

@b-studios b-studios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :)

@b-studios b-studios merged commit 19089d3 into effekt-lang:master Sep 13, 2024
2 checks passed
@b-studios
Copy link
Collaborator

Let's keep the optimizations discussed above in mind, but ignore them for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants