[llvm] b881782 - Support critical edge splitting for jump tables

Matthias Braun via llvm-commits llvm-commits at lists.llvm.org
Wed May 10 20:45:15 PDT 2023


Author: Matthias Braun
Date: 2023-05-10T20:30:52-07:00
New Revision: b8817825b9dcb45f204d3a3a9056f929e12c7a3b

URL: https://github.com/llvm/llvm-project/commit/b8817825b9dcb45f204d3a3a9056f929e12c7a3b
DIFF: https://github.com/llvm/llvm-project/commit/b8817825b9dcb45f204d3a3a9056f929e12c7a3b.diff

LOG: Support critical edge splitting for jump tables

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.

Differential Revision: https://reviews.llvm.org/D140975

Added: 
    llvm/test/CodeGen/X86/switch-jmp-edge-split.mir

Modified: 
    llvm/include/llvm/CodeGen/TargetInstrInfo.h
    llvm/lib/CodeGen/MachineBasicBlock.cpp
    llvm/lib/Target/X86/X86InstrInfo.cpp
    llvm/lib/Target/X86/X86InstrInfo.h
    llvm/test/CodeGen/X86/switch-phi-const.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 7d8265ad413c..58cf89f77070 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -1005,6 +1005,10 @@ class TargetInstrInfo : public MCInstrInfo {
     return false;
   }
 
+  /// Return an index for MachineJumpTableInfo if \p insn is an indirect jump
+  /// using a jump table, otherwise -1.
+  virtual int getJumpTableIndex(const MachineInstr &MI) const { return -1; }
+
 protected:
   /// Target-dependent implementation for IsCopyInstr.
   /// If the specific machine instruction is a instruction that moves/copies

diff  --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 47a475a668af..48b2aa40cab6 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -18,6 +18,7 @@
 #include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineLoopInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/SlotIndexes.h"
@@ -664,6 +665,15 @@ void MachineBasicBlock::moveAfter(MachineBasicBlock *NewBefore) {
   getParent()->splice(++NewBefore->getIterator(), getIterator());
 }
 
+static int findJumpTableIndex(const MachineBasicBlock &MBB) {
+  MachineBasicBlock::const_iterator TerminatorI = MBB.getFirstTerminator();
+  if (TerminatorI == MBB.end())
+    return -1;
+  const MachineInstr &Terminator = *TerminatorI;
+  const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
+  return TII->getJumpTableIndex(Terminator);
+}
+
 void MachineBasicBlock::updateTerminator(
     MachineBasicBlock *PreviousLayoutSuccessor) {
   LLVM_DEBUG(dbgs() << "Updating terminators on " << printMBBReference(*this)
@@ -1033,6 +1043,50 @@ MachineBasicBlock *MachineBasicBlock::splitAt(MachineInstr &MI,
   return SplitBB;
 }
 
+// Returns `true` if there are possibly other users of the jump table at
+// `JumpTableIndex` except for the ones in `IgnoreMBB`.
+static bool jumpTableHasOtherUses(const MachineFunction &MF,
+                                  const MachineBasicBlock &IgnoreMBB,
+                                  int JumpTableIndex) {
+  assert(JumpTableIndex >= 0 && "need valid index");
+  const MachineJumpTableInfo &MJTI = *MF.getJumpTableInfo();
+  const MachineJumpTableEntry &MJTE = MJTI.getJumpTables()[JumpTableIndex];
+  // Take any basic block from the table; every user of the jump table must
+  // show up in the predecessor list.
+  const MachineBasicBlock *MBB = nullptr;
+  for (MachineBasicBlock *B : MJTE.MBBs) {
+    if (B != nullptr) {
+      MBB = B;
+      break;
+    }
+  }
+  if (MBB == nullptr)
+    return true; // can't rule out other users if there isn't any block.
+  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
+  SmallVector<MachineOperand, 4> Cond;
+  for (MachineBasicBlock *Pred : MBB->predecessors()) {
+    if (Pred == &IgnoreMBB)
+      continue;
+    MachineBasicBlock *DummyT = nullptr;
+    MachineBasicBlock *DummyF = nullptr;
+    Cond.clear();
+    if (!TII.analyzeBranch(*Pred, DummyT, DummyF, Cond,
+                           /*AllowModify=*/false)) {
+      // analyzable direct jump
+      continue;
+    }
+    int PredJTI = findJumpTableIndex(*Pred);
+    if (PredJTI >= 0) {
+      if (PredJTI == JumpTableIndex)
+        return true;
+      continue;
+    }
+    // Be conservative for unanalyzable jumps.
+    return true;
+  }
+  return false;
+}
+
 MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
     MachineBasicBlock *Succ, Pass &P,
     std::vector<SparseBitVector<>> *LiveInSets) {
@@ -1044,6 +1098,16 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
   DebugLoc DL;  // FIXME: this is nowhere
 
   MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
+
+  // Is there an indirect jump with jump table?
+  bool ChangedIndirectJump = false;
+  int JTI = findJumpTableIndex(*this);
+  if (JTI >= 0) {
+    MachineJumpTableInfo &MJTI = *MF->getJumpTableInfo();
+    MJTI.ReplaceMBBInJumpTable(JTI, Succ, NMBB);
+    ChangedIndirectJump = true;
+  }
+
   MF->insert(std::next(MachineFunction::iterator(this)), NMBB);
   LLVM_DEBUG(dbgs() << "Splitting critical edge: " << printMBBReference(*this)
                     << " -- " << printMBBReference(*NMBB) << " -- "
@@ -1109,7 +1173,9 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
   // as the fallthrough successor
   if (Succ == PrevFallthrough)
     PrevFallthrough = NMBB;
-  updateTerminator(PrevFallthrough);
+
+  if (!ChangedIndirectJump)
+    updateTerminator(PrevFallthrough);
 
   if (Indexes) {
     SmallVector<MachineInstr*, 4> NewTerminators;
@@ -1284,8 +1350,13 @@ bool MachineBasicBlock::canSplitCriticalEdge(
   if (MF->getTarget().requiresStructuredCFG())
     return false;
 
+  // Do we have an Indirect jump with a jumptable that we can rewrite?
+  int JTI = findJumpTableIndex(*this);
+  if (JTI >= 0 && !jumpTableHasOtherUses(*MF, *this, JTI))
+    return true;
+
   // We may need to update this's terminator, but we can't do that if
-  // analyzeBranch fails. If this uses a jump table, we won't touch it.
+  // analyzeBranch fails.
   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
   MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
   SmallVector<MachineOperand, 4> Cond;

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 859079496710..76d25bc26193 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -3204,6 +3204,65 @@ bool X86InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
   return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, CondBranches, AllowModify);
 }
 
+static int getJumpTableIndexFromAddr(const MachineInstr &MI) {
+  const MCInstrDesc &Desc = MI.getDesc();
+  int MemRefBegin = X86II::getMemoryOperandNo(Desc.TSFlags);
+  assert(MemRefBegin >= 0 && "instr should have memory operand");
+  MemRefBegin += X86II::getOperandBias(Desc);
+
+  const MachineOperand &MO = MI.getOperand(MemRefBegin + X86::AddrDisp);
+  if (!MO.isJTI())
+    return -1;
+
+  return MO.getIndex();
+}
+
+static int getJumpTableIndexFromReg(const MachineRegisterInfo &MRI,
+                                    Register Reg) {
+  if (!Reg.isVirtual())
+    return -1;
+  MachineInstr *MI = MRI.getUniqueVRegDef(Reg);
+  if (MI == nullptr)
+    return -1;
+  unsigned Opcode = MI->getOpcode();
+  if (Opcode != X86::LEA64r && Opcode != X86::LEA32r)
+    return -1;
+  return getJumpTableIndexFromAddr(*MI);
+}
+
+int X86InstrInfo::getJumpTableIndex(const MachineInstr &MI) const {
+  unsigned Opcode = MI.getOpcode();
+  // Switch-jump pattern for non-PIC code looks like:
+  //   JMP64m $noreg, 8, %X, %jump-table.X, $noreg
+  if (Opcode == X86::JMP64m || Opcode == X86::JMP32m) {
+    return getJumpTableIndexFromAddr(MI);
+  }
+  // The pattern for PIC code looks like:
+  //   %0 = LEA64r $rip, 1, $noreg, %jump-table.X
+  //   %1 = MOVSX64rm32 %0, 4, XX, 0, $noreg
+  //   %2 = ADD64rr %1, %0
+  //   JMP64r %2
+  if (Opcode == X86::JMP64r || Opcode == X86::JMP32r) {
+    Register Reg = MI.getOperand(0).getReg();
+    if (!Reg.isVirtual())
+      return -1;
+    const MachineFunction &MF = *MI.getParent()->getParent();
+    const MachineRegisterInfo &MRI = MF.getRegInfo();
+    MachineInstr *Add = MRI.getUniqueVRegDef(Reg);
+    if (Add == nullptr)
+      return -1;
+    if (Add->getOpcode() != X86::ADD64rr && Add->getOpcode() != X86::ADD32rr)
+      return -1;
+    int JTI1 = getJumpTableIndexFromReg(MRI, Add->getOperand(1).getReg());
+    if (JTI1 >= 0)
+      return JTI1;
+    int JTI2 = getJumpTableIndexFromReg(MRI, Add->getOperand(2).getReg());
+    if (JTI2 >= 0)
+      return JTI2;
+  }
+  return -1;
+}
+
 bool X86InstrInfo::analyzeBranchPredicate(MachineBasicBlock &MBB,
                                           MachineBranchPredicate &MBP,
                                           bool AllowModify) const {

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h
index 4d1950e68f31..82554032ebd6 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/llvm/lib/Target/X86/X86InstrInfo.h
@@ -327,6 +327,8 @@ class X86InstrInfo final : public X86GenInstrInfo {
                      SmallVectorImpl<MachineOperand> &Cond,
                      bool AllowModify) const override;
 
+  int getJumpTableIndex(const MachineInstr &MI) const override;
+
   std::optional<ExtAddrMode>
   getAddrModeFromMemoryOp(const MachineInstr &MemI,
                           const TargetRegisterInfo *TRI) const override;

diff  --git a/llvm/test/CodeGen/X86/switch-jmp-edge-split.mir b/llvm/test/CodeGen/X86/switch-jmp-edge-split.mir
new file mode 100644
index 000000000000..2ca192efe0e1
--- /dev/null
+++ b/llvm/test/CodeGen/X86/switch-jmp-edge-split.mir
@@ -0,0 +1,251 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=x86_64-- -run-pass=machine-sink -verify-machineinstrs  -o - %s | FileCheck %s
+
+---
+name:            func_no_pic
+tracksRegLiveness: true
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.4', '%bb.1', '%bb.2', '%bb.3' ]
+body:             |
+  ; CHECK-LABEL: name: func_no_pic
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.5(0x20000000), %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000)
+  ; CHECK-NEXT:   liveins: $edi
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gr64_nosp = COPY $rdi
+  ; CHECK-NEXT:   JMP64m $noreg, 8, [[COPY]], %jump-table.0, $noreg :: (load (s64) from jump-table)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.5:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 42
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri1:%[0-9]+]]:gr32 = MOV32ri 6
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri2:%[0-9]+]]:gr32 = MOV32ri 1
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri3:%[0-9]+]]:gr32 = MOV32ri 92
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4:
+  ; CHECK-NEXT:   [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.5, [[MOV32ri1]], %bb.1, [[MOV32ri2]], %bb.2, [[MOV32ri3]], %bb.3
+  ; CHECK-NEXT:   $eax = COPY [[PHI]]
+  ; CHECK-NEXT:   RET 0
+  bb.0:
+    successors: %bb.4, %bb.1, %bb.2, %bb.3
+    liveins: $edi
+
+    %0:gr64_nosp = COPY $rdi
+    ; MachineSink should split the critical edges and sink the next two
+    ; insns out of the switch-jump header into new less frequently executed
+    ; blocks.
+    %1:gr32 = MOV32ri 42
+    JMP64m $noreg, 8, %0, %jump-table.0, $noreg :: (load (s64) from jump-table)
+
+  bb.1:
+    %2:gr32 = MOV32ri 6
+    JMP_1 %bb.4
+
+  bb.2:
+    %3:gr32 = MOV32ri 1
+    JMP_1 %bb.4
+
+  bb.3:
+    %4:gr32 = MOV32ri 92
+    JMP_1 %bb.4
+
+  bb.4:
+    %5:gr32 = PHI %1, %bb.0, %2, %bb.1, %3, %bb.2, %4, %bb.3
+    $eax = COPY %5
+    RET 0
+
+...
+---
+name:            func_pic
+tracksRegLiveness: true
+jumpTable:
+  kind:            label-
diff erence32
+  entries:
+    - id:              0
+      blocks:          [ '%bb.4', '%bb.1', '%bb.2', '%bb.3' ]
+body:             |
+  ; CHECK-LABEL: name: func_pic
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.5(0x20000000), %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000)
+  ; CHECK-NEXT:   liveins: $edi
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gr64_nosp = COPY $rdi
+  ; CHECK-NEXT:   [[LEA64r:%[0-9]+]]:gr64 = LEA64r $rip, 1, $noreg, %jump-table.0, $noreg
+  ; CHECK-NEXT:   [[MOVSX64rm32_:%[0-9]+]]:gr64 = MOVSX64rm32 [[LEA64r]], 4, [[COPY]], 0, $noreg :: (load (s32) from jump-table)
+  ; CHECK-NEXT:   [[ADD64rr:%[0-9]+]]:gr64 = ADD64rr [[MOVSX64rm32_]], [[LEA64r]], implicit-def dead $eflags
+  ; CHECK-NEXT:   JMP64r killed [[ADD64rr]]
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.5:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 42
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri1:%[0-9]+]]:gr32 = MOV32ri 6
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri2:%[0-9]+]]:gr32 = MOV32ri 1
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.4(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri3:%[0-9]+]]:gr32 = MOV32ri 92
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4:
+  ; CHECK-NEXT:   [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.5, [[MOV32ri1]], %bb.1, [[MOV32ri2]], %bb.2, [[MOV32ri3]], %bb.3
+  ; CHECK-NEXT:   $eax = COPY [[PHI]]
+  ; CHECK-NEXT:   RET 0
+  bb.0:
+    successors: %bb.4, %bb.1, %bb.2, %bb.3
+    liveins: $edi
+
+    %0:gr64_nosp = COPY $rdi
+    ; MachineSink should split the critical edges and sink the next two
+    ; insns out of the switch-jump header into new less frequently executed
+    ; blocks.
+    %1:gr32 = MOV32ri 42
+    %2:gr64 = LEA64r $rip, 1, $noreg, %jump-table.0, $noreg
+    %3:gr64 = MOVSX64rm32 %2, 4, %0, 0, $noreg :: (load (s32) from jump-table)
+    %4:gr64 = ADD64rr %3, %2, implicit-def dead $eflags
+    JMP64r killed %4
+
+  bb.1:
+    %5:gr32 = MOV32ri 6
+    JMP_1 %bb.4
+
+  bb.2:
+    %6:gr32 = MOV32ri 1
+    JMP_1 %bb.4
+
+  bb.3:
+    %7:gr32 = MOV32ri 92
+    JMP_1 %bb.4
+
+  bb.4:
+    %8:gr32 = PHI %1, %bb.0, %5, %bb.1, %6, %bb.2, %7, %bb.3
+    $eax = COPY %8
+    RET 0
+
+...
+---
+name:            multiple_jump_table_users
+tracksRegLiveness: true
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.6', '%bb.3', '%bb.4', '%bb.5' ]
+body:             |
+  ; CHECK-LABEL: name: multiple_jump_table_users
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $edi
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gr64_nosp = COPY $rdi
+  ; CHECK-NEXT:   CMP64ri8 [[COPY]], 42, implicit-def $eflags
+  ; CHECK-NEXT:   JCC_1 %bb.1, 15, implicit $eflags
+  ; CHECK-NEXT:   JMP_1 %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.6(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000), %bb.5(0x20000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   INLINEASM &"", 1 /* sideeffect attdialect */
+  ; CHECK-NEXT:   [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 13
+  ; CHECK-NEXT:   JMP64m $noreg, 8, [[COPY]], %jump-table.0, $noreg :: (load (s64) from jump-table)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.6(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000), %bb.5(0x20000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   INLINEASM &"", 1 /* sideeffect attdialect */
+  ; CHECK-NEXT:   [[MOV32ri1:%[0-9]+]]:gr32 = MOV32ri 42
+  ; CHECK-NEXT:   JMP64m $noreg, 8, [[COPY]], %jump-table.0, $noreg :: (load (s64) from jump-table)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.6(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri2:%[0-9]+]]:gr32 = MOV32ri 6
+  ; CHECK-NEXT:   JMP_1 %bb.6
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4:
+  ; CHECK-NEXT:   successors: %bb.6(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri3:%[0-9]+]]:gr32 = MOV32ri 1
+  ; CHECK-NEXT:   JMP_1 %bb.6
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.5:
+  ; CHECK-NEXT:   successors: %bb.6(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32ri4:%[0-9]+]]:gr32 = MOV32ri 92
+  ; CHECK-NEXT:   JMP_1 %bb.6
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.6:
+  ; CHECK-NEXT:   [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.1, [[MOV32ri1]], %bb.2, [[MOV32ri2]], %bb.3, [[MOV32ri3]], %bb.4, [[MOV32ri4]], %bb.5
+  ; CHECK-NEXT:   $eax = COPY [[PHI]]
+  ; CHECK-NEXT:   RET 0
+  bb.0:
+    liveins: $edi
+    %0:gr64_nosp = COPY $rdi
+
+    CMP64ri8 %0:gr64_nosp, 42, implicit-def $eflags
+    JCC_1 %bb.1, 15, implicit $eflags
+    JMP_1 %bb.2
+
+  bb.1:
+    successors: %bb.6, %bb.3, %bb.4, %bb.5
+    INLINEASM &"", 1 /* sideeffect attdialect */
+    %1:gr32 = MOV32ri 13
+    JMP64m $noreg, 8, %0, %jump-table.0, $noreg :: (load (s64) from jump-table)
+
+  bb.2:
+    successors: %bb.6, %bb.3, %bb.4, %bb.5
+    INLINEASM &"", 1 /* sideeffect attdialect */
+    %2:gr32 = MOV32ri 42
+    ; This is a 2d user of jump-table.0 . This case is not supported yet;
+    ; Should not attempt edge splitting.
+    JMP64m $noreg, 8, %0, %jump-table.0, $noreg :: (load (s64) from jump-table)
+
+  bb.3:
+    %3:gr32 = MOV32ri 6
+    JMP_1 %bb.6
+
+  bb.4:
+    %4:gr32 = MOV32ri 1
+    JMP_1 %bb.6
+
+  bb.5:
+    %5:gr32 = MOV32ri 92
+    JMP_1 %bb.6
+
+  bb.6:
+    %6:gr32 = PHI %1, %bb.1, %2, %bb.2, %3, %bb.3, %4, %bb.4, %5, %bb.5
+    $eax = COPY %6
+    RET 0
+...

diff  --git a/llvm/test/CodeGen/X86/switch-phi-const.ll b/llvm/test/CodeGen/X86/switch-phi-const.ll
index 08ff1a03d8e4..dba7666a14fc 100644
--- a/llvm/test/CodeGen/X86/switch-phi-const.ll
+++ b/llvm/test/CodeGen/X86/switch-phi-const.ll
@@ -7,35 +7,37 @@ define void @switch_phi_const(i32 %x) {
 ; CHECK-LABEL: switch_phi_const:
 ; CHECK:       # %bb.0: # %bb0
 ; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
-; CHECK-NEXT:    leal -1(%rdi), %ecx
-; CHECK-NEXT:    cmpl $54, %ecx
-; CHECK-NEXT:    ja .LBB0_8
+; CHECK-NEXT:    leal -1(%rdi), %eax
+; CHECK-NEXT:    cmpl $54, %eax
+; CHECK-NEXT:    ja .LBB0_9
 ; CHECK-NEXT:  # %bb.1: # %bb0
-; CHECK-NEXT:    movl $42, %eax
-; CHECK-NEXT:    jmpq *.LJTI0_0(,%rcx,8)
-; CHECK-NEXT:  .LBB0_2: # %case_7
+; CHECK-NEXT:    jmpq *.LJTI0_0(,%rax,8)
+; CHECK-NEXT:  .LBB0_3: # %case_7
 ; CHECK-NEXT:    movq g at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movl (%rax), %edi
 ; CHECK-NEXT:    movq effect at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movl $7, (%rax)
-; CHECK-NEXT:  .LBB0_3: # %case_1_loop
+; CHECK-NEXT:  .LBB0_4: # %case_1_loop
 ; CHECK-NEXT:    movq effect at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movl $1, (%rax)
-; CHECK-NEXT:  .LBB0_4: # %case_5
+; CHECK-NEXT:  .LBB0_5: # %case_5
 ; CHECK-NEXT:    movq effect at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movl $5, (%rax)
-; CHECK-NEXT:  .LBB0_5: # %case_13
+; CHECK-NEXT:  .LBB0_6: # %case_13
 ; CHECK-NEXT:    movq effect at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movl $13, (%rax)
-; CHECK-NEXT:  .LBB0_6: # %case_42
+; CHECK-NEXT:  .LBB0_7: # %case_42
 ; CHECK-NEXT:    movq effect at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movl %edi, (%rax)
 ; CHECK-NEXT:    movl $55, %eax
-; CHECK-NEXT:  .LBB0_7: # %case_55
+; CHECK-NEXT:  .LBB0_8: # %case_55
 ; CHECK-NEXT:    movq effect at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movl %eax, (%rcx)
-; CHECK-NEXT:  .LBB0_8: # %default
+; CHECK-NEXT:  .LBB0_9: # %default
 ; CHECK-NEXT:    retq
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    movl $42, %eax
+; CHECK-NEXT:    jmp .LBB0_8
 bb0:
   switch i32 %x, label %default [
   i32 1, label %case_1_loop
@@ -94,34 +96,36 @@ define void @switch_trunc_phi_const(i32 %x) {
 ; CHECK-NEXT:    movzbl %dil, %eax
 ; CHECK-NEXT:    leal -1(%rax), %ecx
 ; CHECK-NEXT:    cmpl $54, %ecx
-; CHECK-NEXT:    ja .LBB1_8
+; CHECK-NEXT:    ja .LBB1_9
 ; CHECK-NEXT:  # %bb.1: # %bb0
-; CHECK-NEXT:    movl $3895, %edx # imm = 0xF37
 ; CHECK-NEXT:    jmpq *.LJTI1_0(,%rcx,8)
-; CHECK-NEXT:  .LBB1_8: # %default
+; CHECK-NEXT:  .LBB1_2:
+; CHECK-NEXT:    movl $3895, %eax # imm = 0xF37
+; CHECK-NEXT:    jmp .LBB1_7
+; CHECK-NEXT:  .LBB1_9: # %default
 ; CHECK-NEXT:    retq
-; CHECK-NEXT:  .LBB1_2: # %case_1_loop
+; CHECK-NEXT:  .LBB1_3: # %case_1_loop
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movq $1, (%rcx)
-; CHECK-NEXT:  .LBB1_3: # %case_5
+; CHECK-NEXT:  .LBB1_4: # %case_5
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movq $5, (%rcx)
-; CHECK-NEXT:  .LBB1_4: # %case_13
+; CHECK-NEXT:  .LBB1_5: # %case_13
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movq $13, (%rcx)
-; CHECK-NEXT:  .LBB1_5: # %case_42
+; CHECK-NEXT:  .LBB1_6: # %case_42
+; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
+; CHECK-NEXT:    movq %rax, (%rcx)
+; CHECK-NEXT:    movl $55, %eax
+; CHECK-NEXT:  .LBB1_7: # %case_55
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movq %rax, (%rcx)
-; CHECK-NEXT:    movl $55, %edx
-; CHECK-NEXT:  .LBB1_6: # %case_55
-; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rax
-; CHECK-NEXT:    movq %rdx, (%rax)
-; CHECK-NEXT:  .LBB1_7: # %case_7
+; CHECK-NEXT:  .LBB1_8: # %case_7
 ; CHECK-NEXT:    movq g64 at GOTPCREL(%rip), %rax
 ; CHECK-NEXT:    movq (%rax), %rax
 ; CHECK-NEXT:    movq effect64 at GOTPCREL(%rip), %rcx
 ; CHECK-NEXT:    movq $7, (%rcx)
-; CHECK-NEXT:    jmp .LBB1_2
+; CHECK-NEXT:    jmp .LBB1_3
 bb0:
   %x_trunc = trunc i32 %x to i8
   switch i8 %x_trunc, label %default [


        


More information about the llvm-commits mailing list