This is an archive of the discontinued LLVM Phabricator instance.

Support critical edge splitting for jump tables
ClosedPublic

Authored by MatzeB on Jan 4 2023, 6:07 AM.

Details

Summary

Add support for splitting critical edges coming from an indirect jump
using a jump table ("switch jumps").

This introduces the TargetInstrInfo::getJumpTableIndex callback to
allows targets to return an index into MachineJumpTableInfo for a
given indirect jump. It also updates to
MachineBasicBlock::SplitCriticalEdge to allow splitting of critical
edges by rewriting jump table entries.

This is largely based on work done by Zhixuan Huan in D132202.

Diff Detail

Event Timeline

MatzeB created this revision.Jan 4 2023, 6:07 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 4 2023, 6:07 AM
MatzeB requested review of this revision.Jan 4 2023, 6:07 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 4 2023, 6:07 AM
MatzeB updated this revision to Diff 510956.Apr 4 2023, 3:55 PM

rebase and ping.

craig.topper added inline comments.Apr 5 2023, 4:55 PM
llvm/lib/Target/X86/X86InstrInfo.cpp
3238

The non-PIC code has the %X scaled by 8, but the PIC code doesn't show a scale. What accounts for the difference?

3244

Drop else after return

MatzeB updated this revision to Diff 512275.Apr 10 2023, 3:40 PM
MatzeB added inline comments.
llvm/lib/Target/X86/X86InstrInfo.cpp
3238

The full code pattern looks something like with the scaling happening in the MOVSX64rm32. I just didn't explicitely mention it as we don't bother looking at that part of the pattern because we only need to find the %jump-table operand. It looks something like this:

%XX = ...
%0:gr64 = LEA64r $rip, 1, $noreg, %jump-table.0, $noreg
%1:gr64 = MOVSX64rm32 %0:gr64, 4, %XX:gr64_nosp, 0, $noreg :: (load (s32) from jump-table)
%2:gr64 = ADD64rr %1:gr64(tied-def 0), %0:gr64, implicit-def dead $eflags

I will update the comment here to reduce the confusion.

MatzeB marked 2 inline comments as done.Apr 10 2023, 3:41 PM
efriedma added inline comments.Apr 10 2023, 4:25 PM
llvm/lib/CodeGen/MachineBasicBlock.cpp
1106

Have we proven at this point that this jump is the only use of the jump table in question? With optimizations like tail duplication, you could have multiple basic blocks referencing the same table.

MatzeB updated this revision to Diff 512631.Apr 11 2023, 5:39 PM
  • Fix unnecessary/dead jump getting added behind the indirect jump
  • Ensure that jump table does not have multiple users and do not split otherwise
MatzeB added inline comments.Apr 11 2023, 5:41 PM
llvm/lib/CodeGen/MachineBasicBlock.cpp
1106

Good point!

As far as I can tell this case is somewhat rare as most switch-jumps are preceded by a range check which is not profitable for tail-duplication. Given that I decided to just detect and not performing the edge splitting in case of multiple users.

MatzeB updated this revision to Diff 512632.Apr 11 2023, 5:44 PM
MatzeB marked an inline comment as done.
MatzeB updated this revision to Diff 512635.Apr 11 2023, 6:13 PM
craig.topper added inline comments.May 2 2023, 12:53 PM
llvm/lib/Target/X86/X86InstrInfo.cpp
3243

I'm not sure I understand this code. The MOVSXrm32 is loading from %0, sign extending it, and then adds what it loaded also to %0?

MatzeB added inline comments.May 8 2023, 9:14 AM
llvm/lib/Target/X86/X86InstrInfo.cpp
3243

This is how clang generates the code. I mention it here as a reminder for the pattern the code below is searching for.

If you look at the assembly of an example compiled with -fPIC you see that the entries in the table record the basic block address relative to the beginning of the jump table. Hence we first need to load from the table and in a 2nd step add the base address of the table to get the final address.

I see something like this for small examples:

   ...
   leaq    .LJTI0_0(%rip), %rax
   movslq  (%rax,%rdi,4), %rcx
   addq    %rax, %rcx
   jmpq    *%rcx
.LBB0_2:
   ...
.LBB0_3:
   ...
...

...

.LJTI0_0:
   .long   .LBB0_2-.LJTI0_0
   .long   .LBB0_3-.LJTI0_0
   ...
craig.topper accepted this revision.May 8 2023, 5:10 PM

LGTM

llvm/lib/Target/X86/X86InstrInfo.cpp
3243

Thanks for the explanation.

This revision is now accepted and ready to land.May 8 2023, 5:10 PM
MatzeB updated this revision to Diff 521140.May 10 2023, 4:12 PM
This revision was landed with ongoing or failed builds.May 10 2023, 8:45 PM
This revision was automatically updated to reflect the committed changes.