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

[EVM] Stackification cleans up stack too eagerly #728

Open
akiramenai opened this issue Oct 30, 2024 · 2 comments
Open

[EVM] Stackification cleans up stack too eagerly #728

akiramenai opened this issue Oct 30, 2024 · 2 comments

Comments

@akiramenai
Copy link
Collaborator

akiramenai commented Oct 30, 2024

It looks like stackification attempts to clean up the stack before doing computations. Consider the following example:

define i256 @no_manipulations_needed_no_junk(i256 %a1, i256 %a2, i256 %a3) nounwind {
; CHECK-LABEL: no_manipulations_needed_no_junk:
; CHECK:       ; %bb.0:
; CHECK-NEXT:    JUMPDEST
; CHECK-NEXT:    SWAP1
; CHECK-NEXT:    SWAP2
; CHECK-NEXT:    POP
; CHECK-NEXT:    SUB
; CHECK-NEXT:    SWAP1
; CHECK-NEXT:    JUMP
  %x1 = sub i256 %a1, %a2
  ret i256 %x1
}

Instead of moving %a3 on top of the stack, popping it, and then subtracting, subtracting and then cleaning up would result in better assembly:

JUMPDEST
SUB
SWAP1
POP
SWAP1
JUMP

Other examples showing the same pattern can be found in test/CodeGen/EVM/stack-ops.ll and test/CodeGen/EVM/stack-ops-commutable.ll (e.g. same_arg_alive_with_junk).

@akiramenai
Copy link
Collaborator Author

Note that sometimes, eager cleanup is preferable:

define i256 @swap_first_no_junk(i256 %a1, i256 %a2, i256 %a3, i256 %a4) nounwind {
; CHECK-LABEL: swap_first_no_junk:
; CHECK:       ; %bb.0:
; CHECK-NEXT:    JUMPDEST
; CHECK-NEXT:    SWAP2
; CHECK-NEXT:    POP
; CHECK-NEXT:    POP
; CHECK-NEXT:    SUB
; CHECK-NEXT:    SWAP1
; CHECK-NEXT:    JUMP
  %x1 = sub i256 %a1, %a4
  ret i256 %x1
}

Here it's better to cleanup first and then subtract.

@akiramenai
Copy link
Collaborator Author

The best way to reproduce is

declare i256 @foo(i256, i256, i256, i256)
define i256 @eager_cleanup(i256 %a1, i256 %a2, i256 %a3, i256 %a4, i256 %junk) {
  %result =  call i256 @foo(i256 %a1, i256 %a2, i256 %a3, i256 %a4)
  ret i256 %result
}

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

No branches or pull requests

1 participant