[llvm-branch-commits] [llvm] CodeGen: Add SUCC_ARGS pseudo-instruction (PR #218893)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Aug 26 06:50:14 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/218893

>From 90e8e17c5e899ffb3c094358b55232684952d2a0 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 14 Aug 2026 00:19:43 +0200
Subject: [PATCH] CodeGen: Add SUCC_ARGS pseudo-instruction

The sender half of a block-argument representation for Machine IR: a
"reverse PHI" that forwards values from a predecessor's bottom to a
successor block's arguments along one CFG edge. Operand 0 is the successor
block; the rest are the forwarded value registers, mapped positionally.

Like PHI, SUCC_ARGS is edge-specific: it must stay in its block, so it is
excluded from CSE and hoisting, and it defines no register but is not dead.
SUCC_ARGS are clustered contiguously immediately before the terminators,
mirroring how PHIs are clustered at the top of a block; the verifier
enforces this and the succ_args() range and getBlockEndInsertPt() let
consumers work with the cluster. Inert; no producer emits it yet.

Co-Authored-By: Claude <noreply at anthropic.com> (Claude Opus 4.8)
---
 llvm/include/llvm/CodeGen/MachineBasicBlock.h | 26 ++++++++++++
 llvm/include/llvm/CodeGen/MachineInstr.h      |  1 +
 llvm/include/llvm/Support/TargetOpcodes.def   |  7 ++++
 llvm/include/llvm/Target/Target.td            |  6 +++
 llvm/lib/CodeGen/MachineBasicBlock.cpp        | 13 ++++++
 llvm/lib/CodeGen/MachineCSE.cpp               |  6 +--
 llvm/lib/CodeGen/MachineInstr.cpp             |  5 ++-
 llvm/lib/CodeGen/MachineVerifier.cpp          | 22 ++++++++++
 llvm/test/CodeGen/MIR/X86/succ-args.mir       | 40 +++++++++++++++++++
 .../CodeGen/X86/machine-cse-succ-args.mir     | 34 ++++++++++++++++
 .../CodeGen/X86/machinelicm-succ-args.mir     | 29 ++++++++++++++
 llvm/test/CodeGen/X86/succ-args-not-dead.mir  | 20 ++++++++++
 llvm/test/MachineVerifier/X86/lit.local.cfg   |  2 +
 .../X86/succ-args-clustered.mir               | 19 +++++++++
 .../X86/succ-args-debug-in-cluster.mir        | 21 ++++++++++
 .../MachineVerifier/X86/succ-args-empty.mir   | 33 +++++++++++++++
 .../match-table-imms.td                       |  4 +-
 llvm/test/TableGen/get-named-operand-idx.td   |  4 +-
 18 files changed, 284 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/CodeGen/MIR/X86/succ-args.mir
 create mode 100644 llvm/test/CodeGen/X86/machine-cse-succ-args.mir
 create mode 100644 llvm/test/CodeGen/X86/machinelicm-succ-args.mir
 create mode 100644 llvm/test/CodeGen/X86/succ-args-not-dead.mir
 create mode 100644 llvm/test/MachineVerifier/X86/lit.local.cfg
 create mode 100644 llvm/test/MachineVerifier/X86/succ-args-clustered.mir
 create mode 100644 llvm/test/MachineVerifier/X86/succ-args-debug-in-cluster.mir
 create mode 100644 llvm/test/MachineVerifier/X86/succ-args-empty.mir

diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index d5c31c4b7281b..fd5fc8fe8c1e5 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -403,6 +403,15 @@ class MachineBasicBlock
     return make_range(getFirstTerminator(), end());
   }
 
+  /// Returns a range that iterates over the SUCC_ARGS instructions clustered
+  /// immediately before the terminators of this block.
+  inline iterator_range<iterator> succ_args() {
+    return make_range(getFirstSuccArgs(), getFirstTerminator());
+  }
+  inline iterator_range<const_iterator> succ_args() const {
+    return const_cast<MachineBasicBlock *>(this)->succ_args();
+  }
+
   /// Returns a range that iterates over the phis in the basic block.
   inline iterator_range<iterator> phis() {
     return make_range(begin(), getFirstNonPHI());
@@ -925,6 +934,23 @@ class MachineBasicBlock
     return const_cast<MachineBasicBlock *>(this)->getFirstTerminator();
   }
 
+  /// Returns an iterator to the first SUCC_ARGS instruction of this basic
+  /// block. SUCC_ARGS instructions are clustered immediately before the
+  /// terminators, mirroring how PHIs are clustered at the top of a block. If
+  /// there are none, this returns getFirstTerminator().
+  LLVM_ABI iterator getFirstSuccArgs();
+  const_iterator getFirstSuccArgs() const {
+    return const_cast<MachineBasicBlock *>(this)->getFirstSuccArgs();
+  }
+
+  /// Returns the insertion point for instructions that must go at the end of
+  /// this block, before the SUCC_ARGS cluster and terminators. This is the
+  /// end-of-block analogue of SkipPHIsAndLabels: anything spliced or built
+  /// here stays clear of the SUCC_ARGS cluster, which must remain adjacent to
+  /// the terminators. Equivalent to getFirstSuccArgs().
+  iterator getBlockEndInsertPt() { return getFirstSuccArgs(); }
+  const_iterator getBlockEndInsertPt() const { return getFirstSuccArgs(); }
+
   /// Same getFirstTerminator but it ignores bundles and return an
   /// instr_iterator instead.
   LLVM_ABI instr_iterator getFirstInstrTerminator();
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index b04018e43bbe0..50d82ee0cd46a 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1425,6 +1425,7 @@ class MachineInstr
     return getOpcode() == TargetOpcode::PHI ||
            getOpcode() == TargetOpcode::G_PHI;
   }
+  bool isSuccArgs() const { return getOpcode() == TargetOpcode::SUCC_ARGS; }
   bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
   bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
   bool isInlineAsm() const {
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 549a93b7bec3a..b3d7b8ea1883f 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -27,6 +27,13 @@
 /// Every instruction defined here must also appear in Target.td.
 ///
 HANDLE_TARGET_OPCODE(PHI)
+
+/// SUCC_ARGS - Forwards values along one CFG edge to a successor block's
+/// arguments. Operand 0 is the successor MachineBasicBlock; the rest are the
+/// forwarded value registers, mapped positionally onto that successor's block
+/// arguments.
+HANDLE_TARGET_OPCODE(SUCC_ARGS)
+
 HANDLE_TARGET_OPCODE(INLINEASM)
 HANDLE_TARGET_OPCODE(INLINEASM_BR)
 HANDLE_TARGET_OPCODE(CFI_INSTRUCTION)
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 3acb2531a5466..79c5c25282af2 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1332,6 +1332,12 @@ def PHI : StandardPseudoInstruction {
   let AsmString = "PHINODE";
   let hasSideEffects = false;
 }
+def SUCC_ARGS : StandardPseudoInstruction {
+  let OutOperandList = (outs);
+  let InOperandList = (ins unknown:$succ, unknown:$val0, variable_ops);
+  let AsmString = "SUCC_ARGS";
+  let hasSideEffects = false;
+}
 def INLINEASM : StandardPseudoInstruction {
   let OutOperandList = (outs);
   let InOperandList = (ins variable_ops);
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 08a67935b52f5..977bec06a547a 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -251,6 +251,19 @@ MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() {
   return I;
 }
 
+MachineBasicBlock::iterator MachineBasicBlock::getFirstSuccArgs() {
+  // SUCC_ARGS are clustered contiguously immediately before the terminators,
+  // mirroring how PHIs are clustered at the top of a block. Walk backward from
+  // the first terminator over that cluster; the result is the first SUCC_ARGS,
+  // or the first terminator if there are none. Nothing (not even a debug
+  // instruction) may be interspersed in the cluster, so the succ_args() range
+  // yields only SUCC_ARGS.
+  iterator B = begin(), I = getFirstTerminator();
+  while (I != B && std::prev(I)->isSuccArgs())
+    --I;
+  return I;
+}
+
 MachineBasicBlock::instr_iterator MachineBasicBlock::getFirstInstrTerminator() {
   instr_iterator B = instr_begin(), E = instr_end(), I = E;
   while (I != B && ((--I)->isTerminator() || I->isDebugInstr()))
diff --git a/llvm/lib/CodeGen/MachineCSE.cpp b/llvm/lib/CodeGen/MachineCSE.cpp
index 75a6ad8d6f3c2..2ac740856c439 100644
--- a/llvm/lib/CodeGen/MachineCSE.cpp
+++ b/llvm/lib/CodeGen/MachineCSE.cpp
@@ -394,9 +394,9 @@ bool MachineCSEImpl::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
 }
 
 bool MachineCSEImpl::isCSECandidate(MachineInstr *MI) {
-  if (MI->isPosition() || MI->isPHI() || MI->isImplicitDef() || MI->isKill() ||
-      MI->isInlineAsm() || MI->isDebugInstr() || MI->isJumpTableDebugInfo() ||
-      MI->isFakeUse())
+  if (MI->isPosition() || MI->isPHI() || MI->isSuccArgs() ||
+      MI->isImplicitDef() || MI->isKill() || MI->isInlineAsm() ||
+      MI->isDebugInstr() || MI->isJumpTableDebugInfo() || MI->isFakeUse())
     return false;
 
   // Ignore copies.
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 1067f186208c4..48248af9ca1f0 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -1360,7 +1360,7 @@ bool MachineInstr::isSafeToMove(bool &SawStore) const {
   // Don't touch instructions that have non-trivial invariants.  For example,
   // terminators have to be at the end of a basic block.
   if (isPosition() || isDebugInstr() || isTerminator() ||
-      isJumpTableDebugInfo() || isLifetimeMarker())
+      isJumpTableDebugInfo() || isLifetimeMarker() || isSuccArgs())
     return false;
 
   // Don't touch instructions which can have non-load/store effects.
@@ -1403,6 +1403,9 @@ bool MachineInstr::wouldBeTriviallyDead() const {
   if (isFakeUse())
     return false;
 
+  if (isSuccArgs())
+    return false;
+
   // If we can move an instruction, we can remove it.  Otherwise, it has
   // a side-effect of some sort.
   bool SawStore = false;
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 0d3015e098cf2..dd034d7e5cb73 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -159,6 +159,7 @@ struct MachineVerifier {
 
   const MachineInstr *FirstNonPHI = nullptr;
   const MachineInstr *FirstTerminator = nullptr;
+  const MachineInstr *FirstSuccArgs = nullptr;
   BlockSet FunctionBlocks;
 
   BitVector regsReserved;
@@ -742,6 +743,7 @@ void
 MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
   FirstTerminator = nullptr;
   FirstNonPHI = nullptr;
+  FirstSuccArgs = nullptr;
 
   if (MRI->tracksLiveness() && hasPHIs(*MF)) {
     // If this block has allocatable physical registers live-in, check that
@@ -957,6 +959,19 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {
       OS << "First terminator was:\t" << *FirstTerminator;
     }
   }
+
+  // SUCC_ARGS instructions must be clustered contiguously immediately before
+  // the terminators, mirroring how PHIs are clustered at the top of a block.
+  // Once a SUCC_ARGS has been seen, only more SUCC_ARGS or terminators may
+  // follow - not even debug instructions, so that the succ_args() range (which
+  // spans getFirstSuccArgs()..getFirstTerminator()) yields only SUCC_ARGS.
+  if (MI->isSuccArgs()) {
+    if (!FirstSuccArgs)
+      FirstSuccArgs = MI;
+  } else if (FirstSuccArgs && !MI->isTerminator()) {
+    report("Non-terminator instruction after SUCC_ARGS", MI);
+    OS << "First SUCC_ARGS was:\t" << *FirstSuccArgs;
+  }
 }
 
 // The operands on an INLINEASM instruction must follow a template.
@@ -2360,6 +2375,13 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
   } else if (FirstNonPHI == nullptr)
     FirstNonPHI = MI;
 
+  if (MI->isSuccArgs()) {
+    if (MI->getNumOperands() < 1 || !MI->getOperand(0).isMBB())
+      report("SUCC_ARGS must have a successor block operand", MI);
+    else if (MI->getNumOperands() < 2)
+      report("SUCC_ARGS must forward at least one value", MI);
+  }
+
   // Check the tied operands.
   if (MI->isInlineAsm())
     verifyInlineAsm(MI);
diff --git a/llvm/test/CodeGen/MIR/X86/succ-args.mir b/llvm/test/CodeGen/MIR/X86/succ-args.mir
new file mode 100644
index 0000000000000..5f1faca662ba6
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/succ-args.mir
@@ -0,0 +1,40 @@
+# RUN: llc -mtriple=x86_64-- -run-pass=none -o - %s | FileCheck %s
+# Round-trip test for the SUCC_ARGS pseudo-instruction.
+
+# A single forwarded value.
+---
+name: one_value
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: one_value
+  ; CHECK: SUCC_ARGS %bb.1, %0
+  bb.0:
+    successors: %bb.1
+    %0:gr32 = MOV32ri 7
+    SUCC_ARGS %bb.1, %0
+    JMP_1 %bb.1
+
+  bb.1:
+    %1:gr32 = COPY %0
+    RET64
+...
+
+# Multiple forwarded values on one edge.
+---
+name: many_values
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: many_values
+  ; CHECK: SUCC_ARGS %bb.1, %0, %1, %2
+  bb.0:
+    successors: %bb.1
+    %0:gr32 = MOV32ri 1
+    %1:gr32 = MOV32ri 2
+    %2:gr32 = MOV32ri 3
+    SUCC_ARGS %bb.1, %0, %1, %2
+    JMP_1 %bb.1
+
+  bb.1:
+    %3:gr32 = COPY %0
+    RET64
+...
diff --git a/llvm/test/CodeGen/X86/machine-cse-succ-args.mir b/llvm/test/CodeGen/X86/machine-cse-succ-args.mir
new file mode 100644
index 0000000000000..ed89e3c2e4e1e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/machine-cse-succ-args.mir
@@ -0,0 +1,34 @@
+# RUN: llc -mtriple=x86_64-- -run-pass=machine-cse -o - %s | FileCheck %s
+# SUCC_ARGS is edge-specific and must not be common-subexpression-eliminated,
+# even when a dominating block forwards the same register to the same successor
+# along a different edge. Each predecessor must retain its own SUCC_ARGS.
+
+---
+name: no_cse_succ_args
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: no_cse_succ_args
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $edi, $esi
+    %0:gr32 = COPY $edi
+    %1:gr32 = COPY $esi
+    TEST32rr %0, %0, implicit-def $eflags
+    ; CHECK: SUCC_ARGS %bb.2, %1
+    SUCC_ARGS %bb.2, %1
+    JCC_1 %bb.2, 5, implicit $eflags
+    JMP_1 %bb.1
+
+  ; bb.1 is dominated by bb.0. Its SUCC_ARGS is identical to bb.0's but feeds a
+  ; different edge, so it must not be CSE'd away.
+  ; CHECK: bb.1:
+  ; CHECK: SUCC_ARGS %bb.2, %1
+  bb.1:
+    successors: %bb.2
+    SUCC_ARGS %bb.2, %1
+    JMP_1 %bb.2
+
+  bb.2:
+    $eax = COPY %1
+    RET64 implicit $eax
+...
diff --git a/llvm/test/CodeGen/X86/machinelicm-succ-args.mir b/llvm/test/CodeGen/X86/machinelicm-succ-args.mir
new file mode 100644
index 0000000000000..c1a0360248efc
--- /dev/null
+++ b/llvm/test/CodeGen/X86/machinelicm-succ-args.mir
@@ -0,0 +1,29 @@
+# RUN: llc -mtriple=x86_64-- -run-pass=early-machinelicm -o - %s | FileCheck %s
+# SUCC_ARGS is edge-specific and must not be hoisted out of a loop by
+# MachineLICM, even when its forwarded operands are loop-invariant.
+
+---
+name: no_hoist_succ_args
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: no_hoist_succ_args
+  bb.0:
+    successors: %bb.1
+    liveins: $edi
+    %0:gr32 = COPY $edi
+    %1:gr32 = MOV32ri 7
+    JMP_1 %bb.1
+
+  ; The SUCC_ARGS must remain in the loop body, not be hoisted into bb.0.
+  ; CHECK: bb.1:
+  ; CHECK: SUCC_ARGS %bb.1, %1
+  bb.1:
+    successors: %bb.1, %bb.2
+    TEST32rr %0, %0, implicit-def $eflags
+    SUCC_ARGS %bb.1, %1
+    JCC_1 %bb.1, 5, implicit $eflags
+    JMP_1 %bb.2
+
+  bb.2:
+    RET64
+...
diff --git a/llvm/test/CodeGen/X86/succ-args-not-dead.mir b/llvm/test/CodeGen/X86/succ-args-not-dead.mir
new file mode 100644
index 0000000000000..bf2c83baf2758
--- /dev/null
+++ b/llvm/test/CodeGen/X86/succ-args-not-dead.mir
@@ -0,0 +1,20 @@
+# RUN: llc -mtriple=x86_64-- -run-pass=dead-mi-elimination -o - %s | FileCheck %s
+# A SUCC_ARGS defines no register but is not dead: dead-MI elimination must
+# preserve it.
+
+---
+name: f
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: f
+  bb.0:
+    successors: %bb.1
+    %0:gr32 = MOV32ri 7
+    ; CHECK: SUCC_ARGS %bb.1, %0
+    SUCC_ARGS %bb.1, %0
+    JMP_1 %bb.1
+
+  bb.1:
+    %1:gr32 = COPY %0
+    RET64
+...
diff --git a/llvm/test/MachineVerifier/X86/lit.local.cfg b/llvm/test/MachineVerifier/X86/lit.local.cfg
new file mode 100644
index 0000000000000..42bf50dcc13c3
--- /dev/null
+++ b/llvm/test/MachineVerifier/X86/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "X86" in config.root.targets:
+    config.unsupported = True
diff --git a/llvm/test/MachineVerifier/X86/succ-args-clustered.mir b/llvm/test/MachineVerifier/X86/succ-args-clustered.mir
new file mode 100644
index 0000000000000..fb18c54cd8df8
--- /dev/null
+++ b/llvm/test/MachineVerifier/X86/succ-args-clustered.mir
@@ -0,0 +1,19 @@
+# RUN: not --crash llc %s -mtriple=x86_64-- -run-pass=none -filetype=null 2>&1 | FileCheck %s
+
+# SUCC_ARGS instructions must be clustered contiguously immediately before the
+# terminators. A non-terminator instruction after a SUCC_ARGS is malformed.
+# CHECK: *** Bad machine code: Non-terminator instruction after SUCC_ARGS ***
+---
+name: succ_args_not_clustered
+tracksRegLiveness: true
+body: |
+  bb.0:
+    successors: %bb.1
+    %0:gr32 = MOV32ri 7
+    SUCC_ARGS %bb.1, %0
+    %1:gr32 = MOV32ri 8
+    JMP_1 %bb.1
+
+  bb.1:
+    RET64
+...
diff --git a/llvm/test/MachineVerifier/X86/succ-args-debug-in-cluster.mir b/llvm/test/MachineVerifier/X86/succ-args-debug-in-cluster.mir
new file mode 100644
index 0000000000000..04f598a3a874b
--- /dev/null
+++ b/llvm/test/MachineVerifier/X86/succ-args-debug-in-cluster.mir
@@ -0,0 +1,21 @@
+# RUN: not --crash llc %s -mtriple=x86_64-- -run-pass=none -filetype=null 2>&1 | FileCheck %s
+
+# The SUCC_ARGS cluster must be contiguous: not even a debug instruction may sit
+# between a SUCC_ARGS and the terminators, so that the succ_args() range
+# (spanning getFirstSuccArgs()..getFirstTerminator()) yields only SUCC_ARGS and
+# no consumer misreads a debug instruction's operand 0 as a block.
+# CHECK: *** Bad machine code: Non-terminator instruction after SUCC_ARGS ***
+---
+name: succ_args_debug_in_cluster
+tracksRegLiveness: true
+body: |
+  bb.0:
+    successors: %bb.1
+    %0:gr32 = MOV32ri 7
+    SUCC_ARGS %bb.1, %0
+    DBG_VALUE %0, $noreg
+    JMP_1 %bb.1
+
+  bb.1:
+    RET64
+...
diff --git a/llvm/test/MachineVerifier/X86/succ-args-empty.mir b/llvm/test/MachineVerifier/X86/succ-args-empty.mir
new file mode 100644
index 0000000000000..8723cb58972b0
--- /dev/null
+++ b/llvm/test/MachineVerifier/X86/succ-args-empty.mir
@@ -0,0 +1,33 @@
+# RUN: split-file %s %t
+
+# A SUCC_ARGS must forward at least one value; the bare successor form and the
+# operand-less form are both malformed.
+
+;--- no-values.mir
+# RUN: not --crash llc %t/no-values.mir -mtriple=x86_64-- -run-pass=none -filetype=null 2>&1 | FileCheck %t/no-values.mir
+# CHECK: *** Bad machine code: SUCC_ARGS must forward at least one value ***
+---
+name: no_values
+tracksRegLiveness: true
+body: |
+  bb.0:
+    successors: %bb.1
+    SUCC_ARGS %bb.1
+    JMP_1 %bb.1
+
+  bb.1:
+    RET64
+...
+
+;--- no-successor.mir
+# RUN: not --crash llc %t/no-successor.mir -mtriple=x86_64-- -run-pass=none -filetype=null 2>&1 | FileCheck %t/no-successor.mir
+# CHECK: *** Bad machine code: SUCC_ARGS must have a successor block operand ***
+---
+name: no_successor
+tracksRegLiveness: true
+body: |
+  bb.0:
+    %0:gr32 = MOV32ri 7
+    SUCC_ARGS %0
+    RET64
+...
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td
index e0b802447ea2a..981ba0c8633c5 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td
@@ -34,8 +34,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 //      CHECK: const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:     GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(20), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label 3*/ GIMT_Encode4([[L579:[0-9]+]]),
-// CHECK-NEXT:     /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4([[L462:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
+// CHECK-NEXT:     GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(21), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label 3*/ GIMT_Encode4([[L579:[0-9]+]]),
+// CHECK-NEXT:     /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4([[L462:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
 // CHECK-NEXT:     /*TargetOpcode::G_CONSTANT*//*Label 1*/ GIMT_Encode4([[L493:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
 // CHECK-NEXT:     /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4({{[0-9]+}}),
 // CHECK-NEXT:     // Label 0: @[[L462]]
diff --git a/llvm/test/TableGen/get-named-operand-idx.td b/llvm/test/TableGen/get-named-operand-idx.td
index 31de6faec0da4..fab74e2b6447e 100644
--- a/llvm/test/TableGen/get-named-operand-idx.td
+++ b/llvm/test/TableGen/get-named-operand-idx.td
@@ -98,8 +98,8 @@ defm : RemapAllTargetPseudoPointerOperands<RegClass>;
 // CHECK-NEXT:      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 // CHECK-NEXT:      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 // CHECK-NEXT:      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-// CHECK-NEXT:      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2,
-// CHECK-NEXT:      0,
+// CHECK-NEXT:      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
+// CHECK-NEXT:      2, 0,
 // CHECK-NEXT:    };
 // CHECK-NEXT:    return InstructionIndex[Opcode];
 // CHECK-NEXT:  }



More information about the llvm-branch-commits mailing list