llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.4k stars 11.74k forks source link

[InstCombine] Missed optimization : fold `switch(rol(a, c))` #86161

Open XChy opened 6 months ago

XChy commented 6 months ago

Alive2 proof: https://alive2.llvm.org/ce/z/uPJXhH

Motivating example

define i64 @src(i64 %a) #0 {
entry:
  %rol = call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 62)
  switch i64 %rol, label %default [
    i64 0, label %trap.exit
    i64 5, label %trap.exit
  ]

default:
  call void @dummy()
  br label %trap.exit

trap.exit:
  ret i64 0
}

can be folded to:

define i64 @tgt(i64 %a) #0 {
entry:
  switch i64 %a, label %default [
    i64 0, label %trap.exit
    i64 20, label %trap.exit
  ]

default:
  call void @dummy()
  br label %trap.exit

trap.exit:
  ret i64 0
}

Real-world motivation

This snippet of IR is derived from ruby/signal.c@sig_trap (after O3 pipeline). The example above is a reduced version. If you're interested in the original suboptimal IR and optimal IR, see also:https://godbolt.org/z/E7nz88vbP

Let me know if you can confirm that it's an optimization opportunity, thanks.

EugeneZelenko commented 6 months ago

@XChy: I think will be good idea if you'll request triage role, so you'll be able label issues. Procedure is same as for commit access: https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access.

XChy commented 6 months ago

@XChy: I think will be good idea if you'll request triage role, so you'll be able label issues. Procedure is same as for commit access: https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access.

Oh, sorry for it.. I always forget to add label after opening an issue ):

XChy commented 6 months ago

A generalized proof for transforming fshl(a, a, c1) == c2 to a == fshr(c2, c2, c1) (also reversely): https://alive2.llvm.org/ce/z/JudZWc cc @dtcxzyw

dtcxzyw commented 6 months ago

I think it is easy to handle this optimization in InstCombinerImpl::visitSwitchInst.

llvmbot commented 6 months ago

Hi!

This issue may be a good introductory issue for people new to working on LLVM. If you would like to work on this issue, your first steps are:

  1. In the comments of the issue, request for it to be assigned to you.
  2. Fix the issue locally.
  3. Run the test suite locally. Remember that the subdirectories under test/ create fine-grained testing targets, so you can e.g. use make check-clang-ast to only run Clang's AST tests.
  4. Create a Git commit.
  5. Run git clang-format HEAD~1 to format your changes.
  6. Open a pull request to the upstream repository on GitHub. Detailed instructions can be found in GitHub's documentation.

If you have any further questions about this issue, don't hesitate to ask via a comment in the thread below.

llvmbot commented 6 months ago

@llvm/issue-subscribers-good-first-issue

Author: XChy (XChy)

Alive2 proof: https://alive2.llvm.org/ce/z/uPJXhH ### Motivating example ```llvm define i64 @src(i64 %a) #0 { entry: %rol = call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 62) switch i64 %rol, label %default [ i64 0, label %trap.exit i64 5, label %trap.exit ] default: call void @dummy() br label %trap.exit trap.exit: ret i64 0 } ``` can be folded to: ```llvm define i64 @tgt(i64 %a) #0 { entry: switch i64 %a, label %default [ i64 0, label %trap.exit i64 20, label %trap.exit ] default: call void @dummy() br label %trap.exit trap.exit: ret i64 0 } ``` ### Real-world motivation This snippet of IR is derived from [ruby/signal.c@sig_trap](https://github.com/ruby/ruby/blob/15dc3aaa311b32203d8ffb414bcf9b8e55ce5691/signal.c#L1354) (after O3 pipeline). The example above is a reduced version. If you're interested in the original suboptimal IR and optimal IR, see also:https://godbolt.org/z/E7nz88vbP **Let me know if you can confirm that it's an optimization opportunity, thanks.**
YanWQ-monad commented 6 months ago

Hello, I would like to take it, thanks.

dtcxzyw commented 6 months ago

FYI, SimplifyCFG does the reverse transform :(

https://github.com/llvm/llvm-project/blob/90454a609894ab278a87be2b9f5c49714caba8df/llvm/lib/Transforms/Utils/SimplifyCFG.cpp#L6911-L6996