[llvm] [AMDGPU] Post-RA Peephole for Two-Address Instructions (PR #207731)

Lukas Sommer via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 06:14:20 PDT 2026


https://github.com/sommerlukas created https://github.com/llvm/llvm-project/pull/207731

Post register allocation peephole optimization to turn two-address instructions followed by copies into their three-address equivalent directly targeting the copy-destination registers. This converts cases missed by the `TwoAddressInstructionPass` earlier in the pipeline.

The transformation turns
```
$vgpr2 = two-address instruction ... $vgpr2 ...
$vgpr0 = move/copy $vgpr2
```
into
```
$vgpr0 = three-address instruction ... $vgpr2 ...
```
to avoid the copies. 

Currently, the peephole is narrowly scoped to `V_FMAC` variants for now but could be extended to other instructions that can be converted to three-address instructions and other kinds of copy-like instructions.

This fixes https://github.com/llvm/llvm-project/issues/171891.

>From 68fb22987e679478d9d38fb39cd0b6fd24d4f02a Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Fri, 3 Jul 2026 11:19:06 -0500
Subject: [PATCH 1/3] Initial implementation of post-RA peephole

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp | 179 ++++++++++++++++++-
 1 file changed, 175 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
index a496c9a4daa71..22c6aeec437f8 100644
--- a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineLoopInfo.h"
 #include "llvm/CodeGen/MachinePostDominators.h"
+#include "llvm/CodeGen/ReachingDefAnalysis.h"
 #include "llvm/CodeGen/TargetSchedule.h"
 #include "llvm/Support/BranchProbability.h"
 using namespace llvm;
@@ -39,6 +40,7 @@ class SIPreEmitPeephole {
   const SIInstrInfo *TII = nullptr;
   const SIRegisterInfo *TRI = nullptr;
   MachineLoopInfo *MLI = nullptr;
+  const ReachingDefInfo *RDI = nullptr;
 
   bool optimizeVccBranch(MachineInstr &MI) const;
   void updateMLIBeforeRemovingEdge(MachineBasicBlock *From,
@@ -81,8 +83,34 @@ class SIPreEmitPeephole {
   void addOperandAndMods(MachineInstrBuilder &NewMI, unsigned SrcMods,
                          bool IsHiBits, const MachineOperand &SrcMO);
 
+  // Delayed post-RA conversion from a two-address instruction to a
+  // three-address instruction. The copy instructions become redundant after
+  // retargeting the converted instruction to NewDst.
+  struct ThreeAddressCandidate {
+    MachineInstr *TwoAddrMI;
+    Register NewDst;
+    SmallVector<MachineInstr *, 2> CopiesToRemove;
+
+    ThreeAddressCandidate(MachineInstr &TwoAddrMI, Register NewDst,
+                          ArrayRef<MachineInstr *> Copies)
+        : TwoAddrMI(&TwoAddrMI), NewDst(NewDst), CopiesToRemove(Copies) {}
+  };
+  // Check if \p MaybeCopy is a simple copy of \p Src. If it is a supported
+  // copy, return the destination register of the copy.
+  std::optional<Register> checkCopy(MachineInstr &TwoAddress,
+                                    MachineInstr &MaybeCopy, Register Src);
+  // Check whether the two-address instruction should be replaced with a
+  // three-address instruction to avoid copies of the output registers. If the
+  // replacement should take place, returns the destination register for the
+  // replacement and fills \p Copies with the copy instructions to remove after
+  // the replacement.
+  Register
+  shouldReplaceWithThreeAddress(MachineInstr &MI,
+                                SmallVectorImpl<MachineInstr *> &Copies);
+
 public:
-  bool run(MachineFunction &MF, MachineLoopInfo *MLI);
+  bool run(MachineFunction &MF, MachineLoopInfo *MLI,
+           const ReachingDefInfo *RDI);
 };
 
 class SIPreEmitPeepholeLegacy : public MachineFunctionPass {
@@ -94,13 +122,16 @@ class SIPreEmitPeepholeLegacy : public MachineFunctionPass {
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.addUsedIfAvailable<MachineLoopInfoWrapperPass>();
     AU.addPreserved<MachineLoopInfoWrapperPass>();
+    AU.addRequired<ReachingDefInfoWrapperPass>();
     MachineFunctionPass::getAnalysisUsage(AU);
   }
 
   bool runOnMachineFunction(MachineFunction &MF) override {
     auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
     MachineLoopInfo *MLI = MLIWrapper ? &MLIWrapper->getLI() : nullptr;
-    return SIPreEmitPeephole().run(MF, MLI);
+    const ReachingDefInfo *RDI =
+        &getAnalysis<ReachingDefInfoWrapperPass>().getRDI();
+    return SIPreEmitPeephole().run(MF, MLI, RDI);
   }
 };
 
@@ -763,13 +794,99 @@ MachineInstrBuilder SIPreEmitPeephole::createUnpackedMI(MachineInstr &I,
   return NewMI;
 }
 
+std::optional<Register> SIPreEmitPeephole::checkCopy(MachineInstr &TwoAddress,
+                                                     MachineInstr &MaybeCopy,
+                                                     Register Src) {
+  if (MaybeCopy.isBundle())
+    return std::nullopt;
+
+  switch (MaybeCopy.getOpcode()) {
+  case AMDGPU::COPY:
+  case AMDGPU::V_MOV_B32_e32:
+    break;
+  default:
+    return std::nullopt;
+  }
+
+  MachineOperand CopySrc = MaybeCopy.getOperand(1);
+  if (!CopySrc.isReg() || CopySrc.getReg() != Src)
+    return std::nullopt;
+
+  MachineOperand Dst = MaybeCopy.getOperand(0);
+  if (!Dst.isReg())
+    return std::nullopt;
+
+  Register Reg = Dst.getReg();
+  SmallPtrSet<MachineInstr *, 1> Ignore{&TwoAddress, &MaybeCopy};
+  if (!RDI->isSafeToDefRegAt(&TwoAddress, Reg, Ignore))
+    return std::nullopt;
+
+  if (!RDI->hasSameReachingDef(&TwoAddress, &MaybeCopy, AMDGPU::EXEC))
+    return std::nullopt;
+
+  return Reg;
+}
+
+Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
+    MachineInstr &MI, SmallVectorImpl<MachineInstr *> &Copies) {
+  MachineOperand *Dst = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
+  if (!Dst || !Dst->isReg())
+    return Register();
+
+  SmallVector<Register, 2> DestRegs;
+  Register Sub0 = TRI->getSubReg(Dst->getReg(), AMDGPU::sub0);
+  Register Sub1 = TRI->getSubReg(Dst->getReg(), AMDGPU::sub1);
+  if (Sub0 && Sub1) {
+    DestRegs.push_back(Sub0);
+    DestRegs.push_back(Sub1);
+  } else
+    DestRegs.push_back(Dst->getReg());
+
+  SmallVector<Register, 2> Replacements;
+  for (Register SubReg : DestRegs) {
+    if (!SubReg.isPhysical())
+      return Register();
+    if (RDI->isReachingDefLiveOut(&MI, SubReg))
+      return Register();
+
+    SmallPtrSet<MachineInstr *, 1> Uses;
+    RDI->getReachingLocalUses(&MI, SubReg, Uses);
+    if (Uses.size() != 1)
+      return Register();
+
+    MachineInstr &Use = **Uses.begin();
+    std::optional<Register> MaybeRegister = checkCopy(MI, Use, SubReg);
+
+    if (!MaybeRegister)
+      return Register();
+    Replacements.push_back(*MaybeRegister);
+    Copies.push_back(&Use);
+  }
+
+  if (Replacements.size() > 2)
+    return Register();
+
+  if (Replacements.size() == 1)
+    return Replacements.front();
+
+  Register Tuple = TRI->getMatchingSuperReg(Replacements.front(), AMDGPU::sub0,
+                                            TRI->getVGPR64Class());
+  if (!Tuple)
+    return Register();
+
+  if (TRI->getSubReg(Tuple, AMDGPU::sub1) != Replacements[1].asMCReg())
+    return Register();
+  return Tuple;
+}
+
 PreservedAnalyses
 llvm::SIPreEmitPeepholePass::run(MachineFunction &MF,
                                  MachineFunctionAnalysisManager &MFAM) {
   auto *MLI = MFAM.getCachedResult<MachineLoopAnalysis>(MF);
+  const ReachingDefInfo &RDI = MFAM.getResult<ReachingDefAnalysis>(MF);
   SIPreEmitPeephole Impl;
 
-  if (Impl.run(MF, MLI)) {
+  if (Impl.run(MF, MLI, &RDI)) {
     auto PA = getMachineFunctionPassPreservedAnalyses();
     PA.preserve<MachineLoopAnalysis>();
     return PA;
@@ -778,11 +895,13 @@ llvm::SIPreEmitPeepholePass::run(MachineFunction &MF,
   return PreservedAnalyses::all();
 }
 
-bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo) {
+bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo,
+                            const ReachingDefInfo *ReachingDefInfo) {
   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
   TII = ST.getInstrInfo();
   TRI = &TII->getRegisterInfo();
   MLI = LoopInfo;
+  RDI = ReachingDefInfo;
   bool Changed = false;
 
   MF.RenumberBlocks();
@@ -803,6 +922,58 @@ bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo) {
       }
     }
 
+    // Delayed optimization to replace two-address instructions followed by
+    // copies with a three-address instruction that directly writes to the
+    // copied registers instead. The pattern we seek to optimize is:
+    // $vgpr2_vgpr3 = V_FMAC_F64 ..., $vgpr_2_vgpr3
+    // $vgpr0 = V_MOV_B32 $vgrp2
+    // $vgpr1 = V_MOV_B32 $vgrp3
+    //
+    // This can be optimized to:
+    // $vgpr0_vgpr1 = V_FMA_F64 ..., $vgpr2_vgpr3
+    //
+    // The TwoAddressInstruction pass handles some cases, but bails in more
+    // complex cases.
+    SmallVector<ThreeAddressCandidate> Candidates;
+    // First, collect the candidates. We can't perform the transformation right
+    // away, it would invalidate the iterator.
+    for (auto &MI : make_early_inc_range(MBB.instrs())) {
+      if (MI.isBundle())
+        continue;
+
+      unsigned Opc = MI.getOpcode();
+      if (Opc != AMDGPU::V_FMAC_F64_e64 && Opc != AMDGPU::V_FMAC_F32_e64 &&
+          Opc != AMDGPU::V_FMAC_F64_e32 && Opc != AMDGPU::V_FMAC_F32_e32)
+        continue;
+
+      SmallVector<MachineInstr *, 2> Copies;
+      if (Register Dst = shouldReplaceWithThreeAddress(MI, Copies))
+        Candidates.emplace_back(MI, Dst, Copies);
+    }
+
+    for (ThreeAddressCandidate &Cand : Candidates) {
+      MachineInstr *ThreeAddrsInst =
+          TII->convertToThreeAddress(*Cand.TwoAddrMI, nullptr, nullptr);
+      if (!ThreeAddrsInst)
+        continue;
+      MachineOperand &NewDst = ThreeAddrsInst->getOperand(0);
+      assert(NewDst.isReg());
+
+      const TargetRegisterClass *DstRC =
+          TII->getRegClass(ThreeAddrsInst->getDesc(), NewDst.getOperandNo());
+      if (DstRC && !DstRC->contains(Cand.NewDst.asMCReg())) {
+        ThreeAddrsInst->eraseFromParent();
+        continue;
+      }
+
+      NewDst.setReg(Cand.NewDst);
+      NewDst.setIsRenamable(false);
+      Cand.TwoAddrMI->eraseFromParent();
+      llvm::for_each(Cand.CopiesToRemove,
+                     [](MachineInstr *Copy) { Copy->eraseFromParent(); });
+      Changed = true;
+    }
+
     if (!ST.hasVGPRIndexMode())
       continue;
 

>From 6c8e3f9d29d9c9929ce3fdaf3ce337b5dee66d15 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Mon, 6 Jul 2026 07:00:27 -0500
Subject: [PATCH 2/3] Add and update tests

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 .../CodeGen/AMDGPU/hazard-pass-ordering.mir   |   3 +
 .../AMDGPU/insert-handle-flat-vmem-ds.mir     |   3 +
 .../CodeGen/AMDGPU/insert-skip-from-vcc.mir   |  49 ++++++
 .../CodeGen/AMDGPU/insert-skips-gfx10.mir     |   7 +
 .../CodeGen/AMDGPU/insert-skips-gfx12.mir     |  20 +++
 .../CodeGen/AMDGPU/insert-skips-gfx1250.mir   |   2 +
 llvm/test/CodeGen/AMDGPU/insert-skips-gws.mir |   2 +
 .../AMDGPU/insert-skips-ignored-insts.mir     |   1 +
 llvm/test/CodeGen/AMDGPU/llc-pipeline.ll      |   4 +
 ...hort-exec-branch-on-unconditional-jump.mir |   1 +
 ...emove-short-exec-branches-gpr-idx-mode.mir |   4 +
 ...ort-exec-branches-special-instructions.mir |  10 ++
 .../CodeGen/AMDGPU/set-gpr-idx-peephole.mir   | 164 +++++++++++++++---
 .../AMDGPU/si-pre-emit-peephole-fmac.mir      |  38 ++++
 ...i-pre-emit-peephole-preserve-loop-info.mir |   9 +
 .../AMDGPU/skip-branch-taildup-ret.mir        |   2 +
 16 files changed, 295 insertions(+), 24 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir

diff --git a/llvm/test/CodeGen/AMDGPU/hazard-pass-ordering.mir b/llvm/test/CodeGen/AMDGPU/hazard-pass-ordering.mir
index 093a8e02e0ab1..e4a99f04e3537 100644
--- a/llvm/test/CodeGen/AMDGPU/hazard-pass-ordering.mir
+++ b/llvm/test/CodeGen/AMDGPU/hazard-pass-ordering.mir
@@ -10,8 +10,11 @@
 # GCN-NEXT: s_nop
 # GCN-NEXT: flat_load_dword
 name:            mai_hazard_pass_ordering_optimize_vcc_branch
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $agpr0, $vgpr1
+
     $vgpr0 = V_MOV_B32_e32 1, implicit $exec
     $vgpr2 = V_ACCVGPR_READ_B32_e64 killed $agpr0, implicit $exec
     $sgpr8_sgpr9 = S_MOV_B64 -1
diff --git a/llvm/test/CodeGen/AMDGPU/insert-handle-flat-vmem-ds.mir b/llvm/test/CodeGen/AMDGPU/insert-handle-flat-vmem-ds.mir
index 785f5bed97904..b7b3354afa086 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-handle-flat-vmem-ds.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-handle-flat-vmem-ds.mir
@@ -5,6 +5,7 @@
 ---
 
 name: skip_execz_flat
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_execz_flat
   ; CHECK: bb.0:
@@ -34,6 +35,7 @@ body: |
 ---
 
 name: skip_execz_mubuf
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_execz_mubuf
   ; CHECK: bb.0:
@@ -63,6 +65,7 @@ body: |
 ---
 
 name: skip_execz_ds
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_execz_ds
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/insert-skip-from-vcc.mir b/llvm/test/CodeGen/AMDGPU/insert-skip-from-vcc.mir
index 0004989d42408..0ff5efe8f2f6e 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-skip-from-vcc.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-skip-from-vcc.mir
@@ -8,6 +8,7 @@
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -26,6 +27,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_imm_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -43,6 +45,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_EXECNZ %bb.1, implicit $exec
 name:            and_execnz_imm_vccnz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -60,6 +63,7 @@ body:             |
 # GCN: $vcc = S_AND_B64 $exec, -1, implicit-def $scc
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_imm_vccz_live_scc
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -78,6 +82,7 @@ body:             |
 # GCN: $vcc = S_AND_B64 $exec, -1, implicit-def $scc
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_live_scc
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -96,6 +101,7 @@ body:             |
 # GCN:      $sgpr0_sgpr1 = S_MOV_B64 -1
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_live_sreg
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -114,6 +120,7 @@ body:             |
 # GCN:      $sgpr0_sgpr1 = S_MOV_B64 -1
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_live_sreg_commute
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -133,6 +140,7 @@ body:             |
 # GCN: $vcc = S_AND_B64 $exec, -1, implicit-def $scc
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_live_scc_commute
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -152,6 +160,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_commute
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -170,6 +179,7 @@ body:             |
 # GCN:      $exec = S_MOV_B64 -1
 # GCN-NEXT: S_ENDPGM 0
 name:            and_execz_mov_exec_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -188,6 +198,7 @@ body:             |
 # GCN:      $exec = S_MOV_B64 -1
 # GCN-NEXT: S_BRANCH %bb.1{{$}}
 name:            and_execz_mov_exec_vccnz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -207,6 +218,7 @@ body:             |
 # GCN-NEXT: $sgpr2 = S_MOV_B32 $sgpr1
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_reads_sreg_early
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -227,6 +239,7 @@ body:             |
 # GCN-NEXT: $sgpr2 = S_MOV_B32 $sgpr1
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_reads_sreg_late
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -247,6 +260,7 @@ body:             |
 # GCN-NEXT: $vcc = S_AND_B64 $exec, killed $sgpr0_sgpr1, implicit-def dead $scc
 # GCN-NEXT: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            and_execz_mov_vccz_reads_writes_sreg_early
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -267,6 +281,7 @@ body:             |
 # GCN-NEXT: $sgpr2 = S_MOV_B32 $vcc_lo
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_reads_cond
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -288,6 +303,7 @@ body:             |
 # GCN-NEXT: $vcc = S_AND_B64 $exec, killed $sgpr0_sgpr1, implicit-def dead $scc
 # GCN-NEXT: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            and_execz_mov_vccz_modifies_sreg
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -308,6 +324,7 @@ body:             |
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 # GCN-NEXT: S_ENDPGM 0, implicit $scc
 name:            and_execz_imm_vccz_liveout_scc
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -326,6 +343,7 @@ body:             |
 # W32-NOT: S_AND_
 # W32: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_execz_mov_vccz_w32
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -345,6 +363,7 @@ body:             |
 # GCN-NOT: S_ANDN2_
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            andn2_execz_mov_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -364,6 +383,7 @@ body:             |
 # GCN-NOT: S_ANDN2_
 # GCN: S_BRANCH %bb.1
 name:            andn2_branch_mov_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -383,6 +403,7 @@ body:             |
 # GCN-NOT: S_ANDN2_
 # GCN: S_CBRANCH_EXECNZ %bb.1, implicit $exec
 name:            andn2_execnz_mov_vccnz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -403,6 +424,7 @@ body:             |
 # GCN-NOT: S_CBRANCH
 # GCN-NOT: S_BRANCH
 name:            andn2_no_branch_mov_vccnz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -423,6 +445,7 @@ body:             |
 # GCN: $vcc = S_MOV_B64 0
 # GCN-NEXT: S_BRANCH %bb.1
 name:            and_0_mov
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -443,6 +466,7 @@ body:             |
 # GCN: $vcc = S_MOV_B64 0
 # GCN-NEXT: S_BRANCH %bb.1
 name:            andn2_m1_mov
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -463,6 +487,7 @@ body:             |
 # GCN: $vcc = S_MOV_B64 $exec
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            and_m1_mov
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -483,6 +508,7 @@ body:             |
 # GCN: $vcc = S_MOV_B64 $exec
 # GCN-NEXT: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            andn2_0_mov
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -503,6 +529,7 @@ body:             |
 # GCN: S_AND_
 # GCN-NEXT: S_BRANCH %bb.1
 name:            and_0_scc_req
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -523,6 +550,7 @@ body:             |
 # GCN: S_ANDN2_
 # GCN-NEXT: S_BRANCH %bb.1
 name:            andn2_m1_scc_req
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -542,6 +570,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            and_cmp_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -550,6 +579,8 @@ body:             |
     S_NOP 0
 
   bb.2:
+    liveins: $vgpr0, $sgpr0, $sgpr0_sgpr1
+
     V_CMP_EQ_U32_e32 0, killed $vgpr0, implicit-def $vcc, implicit $exec
     $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
     S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
@@ -561,6 +592,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_VCCNZ %bb.1, implicit killed $vcc
 name:            and_cmp_vccnz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -569,6 +601,8 @@ body:             |
     S_NOP 0
 
   bb.2:
+    liveins: $vgpr0, $sgpr0, $sgpr0_sgpr1
+
     V_CMP_EQ_U32_e32 0, killed $vgpr0, implicit-def $vcc, implicit $exec
     $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
     S_CBRANCH_VCCNZ %bb.1, implicit killed $vcc
@@ -580,6 +614,7 @@ body:             |
 # GCN: $vcc = S_ANDN2_B64 $exec, $vcc, implicit-def dead $scc
 # GCN: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            andn2_cmp_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -588,6 +623,8 @@ body:             |
     S_NOP 0
 
   bb.2:
+    liveins: $vgpr0, $sgpr0, $sgpr0_sgpr1
+
     V_CMP_EQ_U32_e32 0, killed $vgpr0, implicit-def $vcc, implicit $exec
     $vcc = S_ANDN2_B64 $exec, $vcc, implicit-def dead $scc
     S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
@@ -599,6 +636,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            and_cmpclass_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -607,6 +645,8 @@ body:             |
     S_NOP 0
 
   bb.2:
+    liveins: $vgpr0, $sgpr0, $sgpr0_sgpr1
+
     V_CMP_CLASS_F32_e32 killed $sgpr0, killed $vgpr0, implicit-def $vcc, implicit $exec
     $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
     S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
@@ -618,6 +658,7 @@ body:             |
 # GCN-NOT: S_AND_
 # GCN: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            and_cmpx_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -626,6 +667,8 @@ body:             |
     S_NOP 0
 
   bb.2:
+    liveins: $vgpr0, $sgpr0, $sgpr0_sgpr1
+
     V_CMPX_EQ_U32_e32 0, killed $vgpr0, implicit-def $vcc, implicit-def $exec, implicit $exec
     $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
     S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
@@ -638,6 +681,7 @@ body:             |
 # GCN: $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
 # GCN: S_CBRANCH_VCCZ %bb.1, implicit killed $vcc
 name:            and_or_cmp_vccz
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -646,6 +690,8 @@ body:             |
     S_NOP 0
 
   bb.2:
+    liveins: $vgpr0, $sgpr0, $sgpr0_sgpr1
+
     V_CMP_EQ_U32_e32 0, killed $vgpr0, implicit-def $vcc, implicit $exec
     $exec = S_OR_B64 $exec, $sgpr0_sgpr1, implicit-def dead $scc
     $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
@@ -659,6 +705,7 @@ body:             |
 # GCN-NOT: S_
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            issue176578_src0_nonreg
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -678,6 +725,7 @@ body:             |
 # GCN-NOT: S_
 # GCN: S_CBRANCH_EXECZ %bb.1, implicit $exec
 name:            issue176578_src1_nonreg
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
@@ -696,6 +744,7 @@ body:             |
 # GCN: $vcc = S_AND_B64
 # GCN-NEXT: S_CBRANCH_VCCZ %bb.1
 name:            issue176578_nonregs
+tracksRegLiveness: true
 body:             |
   bb.0:
     S_NOP 0
diff --git a/llvm/test/CodeGen/AMDGPU/insert-skips-gfx10.mir b/llvm/test/CodeGen/AMDGPU/insert-skips-gfx10.mir
index 0bf74d96e134e..9f5fc74de2bd6 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-skips-gfx10.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-skips-gfx10.mir
@@ -3,6 +3,7 @@
 
 ---
 name: skip_waitcnt_vscnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_waitcnt_vscnt
   ; CHECK: bb.0:
@@ -33,6 +34,7 @@ body: |
 
 ---
 name: skip_waitcnt_expcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_waitcnt_expcnt
   ; CHECK: bb.0:
@@ -63,6 +65,7 @@ body: |
 
 ---
 name: skip_waitcnt_vmcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_waitcnt_vmcnt
   ; CHECK: bb.0:
@@ -93,6 +96,7 @@ body: |
 
 ---
 name: skip_waitcnt_lgkmcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_waitcnt_lgkmcnt
   ; CHECK: bb.0:
@@ -123,6 +127,7 @@ body: |
 
 ---
 name: skip_wait_idle
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_idle
   ; CHECK: bb.0:
@@ -153,6 +158,7 @@ body: |
 
 ---
 name: skip_bvh
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_bvh
   ; CHECK: bb.0:
@@ -187,6 +193,7 @@ body: |
 
 ---
 name: skip_barrier
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/insert-skips-gfx12.mir b/llvm/test/CodeGen/AMDGPU/insert-skips-gfx12.mir
index bac167fbb1570..cb7c4021787ff 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-skips-gfx12.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-skips-gfx12.mir
@@ -3,6 +3,7 @@
 
 ---
 name: skip_wait_loadcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_loadcnt
   ; CHECK: bb.0:
@@ -33,6 +34,7 @@ body: |
 
 ---
 name: skip_wait_loadcnt_dscnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_loadcnt_dscnt
   ; CHECK: bb.0:
@@ -63,6 +65,7 @@ body: |
 
 ---
 name: skip_wait_storecnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_storecnt
   ; CHECK: bb.0:
@@ -93,6 +96,7 @@ body: |
 
 ---
 name: skip_wait_storecnt_dscnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_storecnt_dscnt
   ; CHECK: bb.0:
@@ -123,6 +127,7 @@ body: |
 
 ---
 name: skip_wait_samplecnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_samplecnt
   ; CHECK: bb.0:
@@ -153,6 +158,7 @@ body: |
 
 ---
 name: skip_wait_bvhcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_bvhcnt
   ; CHECK: bb.0:
@@ -183,6 +189,7 @@ body: |
 
 ---
 name: skip_wait_expcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_expcnt
   ; CHECK: bb.0:
@@ -213,6 +220,7 @@ body: |
 
 ---
 name: skip_wait_dscnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_dscnt
   ; CHECK: bb.0:
@@ -243,6 +251,7 @@ body: |
 
 ---
 name: skip_wait_kmcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_kmcnt
   ; CHECK: bb.0:
@@ -273,6 +282,7 @@ body: |
 
 ---
 name: skip_wait_idle
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_idle
   ; CHECK: bb.0:
@@ -303,6 +313,7 @@ body: |
 
 ---
 name: skip_wait_event
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_event
   ; CHECK: bb.0:
@@ -333,6 +344,7 @@ body: |
 
 ---
 name: skip_barrier_signal_imm
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_signal_imm
   ; CHECK: bb.0:
@@ -363,6 +375,7 @@ body: |
 
 ---
 name: skip_barrier_signal_isfirst_imm
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_signal_isfirst_imm
   ; CHECK: bb.0:
@@ -395,6 +408,7 @@ body: |
 
 ---
 name: skip_barrier_signal_m0
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_signal_m0
   ; CHECK: bb.0:
@@ -427,6 +441,7 @@ body: |
 
 ---
 name: skip_barrier_signal_isfirst_m0
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_signal_isfirst_m0
   ; CHECK: bb.0:
@@ -461,6 +476,7 @@ body: |
 
 ---
 name: skip_barrier_wait
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_wait
   ; CHECK: bb.0:
@@ -491,6 +507,7 @@ body: |
 
 ---
 name: skip_barrier_init_imm
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_init_imm
   ; CHECK: bb.0:
@@ -523,6 +540,7 @@ body: |
 
 ---
 name: skip_barrier_init_m0
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_init_m0
   ; CHECK: bb.0:
@@ -555,6 +573,7 @@ body: |
 
 ---
 name: skip_barrier_join_imm
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_join_imm
   ; CHECK: bb.0:
@@ -585,6 +604,7 @@ body: |
 
 ---
 name: skip_barrier_leave
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_barrier_leave
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/insert-skips-gfx1250.mir b/llvm/test/CodeGen/AMDGPU/insert-skips-gfx1250.mir
index 8a5d9cb6c5632..3854357f5a9ca 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-skips-gfx1250.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-skips-gfx1250.mir
@@ -3,6 +3,7 @@
 
 ---
 name: skip_wait_xcnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_xcnt
   ; CHECK: bb.0:
@@ -33,6 +34,7 @@ body: |
 
 ---
 name: skip_wait_asynccnt
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_wait_asynccnt
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/insert-skips-gws.mir b/llvm/test/CodeGen/AMDGPU/insert-skips-gws.mir
index 3281e4ccda7ab..1c94a1f9b737a 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-skips-gws.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-skips-gws.mir
@@ -5,6 +5,7 @@
 ---
 
 name: skip_gws_init
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_gws_init
   ; CHECK: bb.0:
@@ -36,6 +37,7 @@ body: |
 ---
 
 name: skip_gws_barrier
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: skip_gws_barrier
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/insert-skips-ignored-insts.mir b/llvm/test/CodeGen/AMDGPU/insert-skips-ignored-insts.mir
index 372f22019aefb..3cc1e6e19510d 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-skips-ignored-insts.mir
+++ b/llvm/test/CodeGen/AMDGPU/insert-skips-ignored-insts.mir
@@ -4,6 +4,7 @@
 ---
 
 name: no_count_dbg_value
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: no_count_dbg_value
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
index 070c873798647..93ff015f27b41 100644
--- a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
+++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
@@ -435,6 +435,7 @@
 ; GCN-O1-NEXT:        Insert required mode register values
 ; GCN-O1-NEXT:        SI Insert Hard Clauses
 ; GCN-O1-NEXT:        SI Final Branch Preparation
+; GCN-O1-NEXT:        Reaching Definitions Analysis
 ; GCN-O1-NEXT:        SI peephole optimizations
 ; GCN-O1-NEXT:        Post RA hazard recognizer
 ; GCN-O1-NEXT:        AMDGPU Insert waits for SGPR read hazards
@@ -753,6 +754,7 @@
 ; GCN-O1-OPTS-NEXT:        Insert required mode register values
 ; GCN-O1-OPTS-NEXT:        SI Insert Hard Clauses
 ; GCN-O1-OPTS-NEXT:        SI Final Branch Preparation
+; GCN-O1-OPTS-NEXT:        Reaching Definitions Analysis
 ; GCN-O1-OPTS-NEXT:        SI peephole optimizations
 ; GCN-O1-OPTS-NEXT:        Post RA hazard recognizer
 ; GCN-O1-OPTS-NEXT:        AMDGPU Insert waits for SGPR read hazards
@@ -1076,6 +1078,7 @@
 ; GCN-O2-NEXT:        Insert required mode register values
 ; GCN-O2-NEXT:        SI Insert Hard Clauses
 ; GCN-O2-NEXT:        SI Final Branch Preparation
+; GCN-O2-NEXT:        Reaching Definitions Analysis
 ; GCN-O2-NEXT:        SI peephole optimizations
 ; GCN-O2-NEXT:        Post RA hazard recognizer
 ; GCN-O2-NEXT:        AMDGPU Insert waits for SGPR read hazards
@@ -1412,6 +1415,7 @@
 ; GCN-O3-NEXT:        Insert required mode register values
 ; GCN-O3-NEXT:        SI Insert Hard Clauses
 ; GCN-O3-NEXT:        SI Final Branch Preparation
+; GCN-O3-NEXT:        Reaching Definitions Analysis
 ; GCN-O3-NEXT:        SI peephole optimizations
 ; GCN-O3-NEXT:        Post RA hazard recognizer
 ; GCN-O3-NEXT:        AMDGPU Insert waits for SGPR read hazards
diff --git a/llvm/test/CodeGen/AMDGPU/remove-not-short-exec-branch-on-unconditional-jump.mir b/llvm/test/CodeGen/AMDGPU/remove-not-short-exec-branch-on-unconditional-jump.mir
index f45f48434fa23..e96e9acd7f09f 100644
--- a/llvm/test/CodeGen/AMDGPU/remove-not-short-exec-branch-on-unconditional-jump.mir
+++ b/llvm/test/CodeGen/AMDGPU/remove-not-short-exec-branch-on-unconditional-jump.mir
@@ -5,6 +5,7 @@
 
 ---
 name:            test
+tracksRegLiveness: true
 body:             |
   ; CHECK-LABEL: name: test
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-gpr-idx-mode.mir b/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-gpr-idx-mode.mir
index ee5546befd12d..90dd9f2e83157 100644
--- a/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-gpr-idx-mode.mir
+++ b/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-gpr-idx-mode.mir
@@ -5,6 +5,7 @@
 ---
 
 name: need_skip_gpr_idx_mode
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_gpr_idx_mode
   ; CHECK: bb.0:
@@ -34,6 +35,7 @@ body: |
 ---
 
 name: need_skip_gpr_idx_on
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_gpr_idx_on
   ; CHECK: bb.0:
@@ -67,6 +69,7 @@ body: |
 ---
 
 name: need_skip_gpr_idx_off
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_gpr_idx_off
   ; CHECK: bb.0:
@@ -96,6 +99,7 @@ body: |
 ---
 
 name: need_skip_gpr_idx_idx
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_gpr_idx_idx
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-special-instructions.mir b/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-special-instructions.mir
index 2c8739a87626e..b959d4f36f82e 100644
--- a/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-special-instructions.mir
+++ b/llvm/test/CodeGen/AMDGPU/remove-short-exec-branches-special-instructions.mir
@@ -6,6 +6,7 @@
 ---
 
 name: need_skip_setreg_imm32_b32
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_setreg_imm32_b32
   ; CHECK: bb.0:
@@ -37,6 +38,7 @@ body: |
 ---
 
 name: need_skip_setreg_b32
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_setreg_b32
   ; CHECK: bb.0:
@@ -71,6 +73,7 @@ body: |
 ---
 
 name: need_skip_denorm_mode
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_denorm_mode
   ; CHECK: bb.0:
@@ -101,6 +104,7 @@ body: |
 ---
 
 name: need_skip_round_mode
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_round_mode
   ; CHECK: bb.0:
@@ -131,15 +135,18 @@ body: |
 ---
 
 name: need_skip_writelane_b32
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_writelane_b32
   ; CHECK: bb.0:
   ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   S_CBRANCH_EXECZ %bb.2, implicit $exec
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.1:
   ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   $sgpr0 = IMPLICIT_DEF
   ; CHECK-NEXT:   $vgpr0 = V_WRITELANE_B32 $sgpr0, 0, $vgpr0
@@ -147,10 +154,12 @@ body: |
   ; CHECK-NEXT: bb.2:
   ; CHECK-NEXT:   S_ENDPGM 0
   bb.0:
+    liveins: $vgpr0
     successors: %bb.1, %bb.2
     S_CBRANCH_EXECZ %bb.2, implicit $exec
 
   bb.1:
+    liveins: $vgpr0
     successors: %bb.2
     $sgpr0 = IMPLICIT_DEF
     $vgpr0 = V_WRITELANE_B32 $sgpr0, 0, $vgpr0
@@ -161,6 +170,7 @@ body: |
 
 ---
 name: need_skip_readlane_b32
+tracksRegLiveness: true
 body: |
   ; CHECK-LABEL: name: need_skip_readlane_b32
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/AMDGPU/set-gpr-idx-peephole.mir b/llvm/test/CodeGen/AMDGPU/set-gpr-idx-peephole.mir
index 131656975ec40..29db2860be152 100644
--- a/llvm/test/CodeGen/AMDGPU/set-gpr-idx-peephole.mir
+++ b/llvm/test/CodeGen/AMDGPU/set-gpr-idx-peephole.mir
@@ -5,11 +5,16 @@
 
 ---
 name:            simple
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: simple
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: $vgpr15 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
@@ -23,11 +28,16 @@ body:             |
 
 ---
 name:            salu_in_between
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: salu_in_between
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: $sgpr0 = S_MOV_B32 $sgpr2
     ; GCN-NEXT: $vgpr15 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
@@ -43,10 +53,15 @@ body:             |
 
 ---
 name:            meta_in_between
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
     ; GCN-LABEL: name: meta_in_between
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: KILL $sgpr0
     ; GCN-NEXT: $sgpr0 = IMPLICIT_DEF
@@ -64,11 +79,16 @@ body:             |
 
 ---
 name:            valu_write_in_between
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: valu_write_in_between
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: $vgpr20 = V_MOV_B32_indirect_read 1, implicit $exec, implicit $m0
@@ -86,11 +106,16 @@ body:             |
 
 ---
 name:            valu_read_in_between
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: valu_read_in_between
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: V_NOP_e32 implicit $exec, implicit $vgpr0
@@ -108,11 +133,16 @@ body:             |
 
 ---
 name:            changed_index
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: changed_index
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: $sgpr2 = S_MOV_B32 1
@@ -130,11 +160,16 @@ body:             |
 
 ---
 name:            implicitly_changed_index
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: implicitly_changed_index
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: S_NOP 0, implicit-def $sgpr2
@@ -152,11 +187,16 @@ body:             |
 
 ---
 name:            changed_m0
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: changed_m0
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: $m0 = S_MOV_B32 1
@@ -174,11 +214,16 @@ body:             |
 
 ---
 name:            implicitly_changed_m0
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: implicitly_changed_m0
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: S_NOP 0, implicit-def $m0
@@ -196,11 +241,16 @@ body:             |
 
 ---
 name:            same_imm_index
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: same_imm_index
-    ; GCN: S_SET_GPR_IDX_ON 1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON 1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: $vgpr15 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
@@ -214,11 +264,16 @@ body:             |
 
 ---
 name:            different_imm_index
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: different_imm_index
-    ; GCN: S_SET_GPR_IDX_ON 1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON 1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: S_SET_GPR_IDX_ON 2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
@@ -234,11 +289,16 @@ body:             |
 
 ---
 name:            different_gpr_index
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: different_gpr_index
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: S_SET_GPR_IDX_ON killed $sgpr1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
@@ -254,11 +314,16 @@ body:             |
 
 ---
 name:            different_gpr_index_then_same_index
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: different_gpr_index_then_same_index
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
@@ -280,11 +345,16 @@ body:             |
 
 ---
 name:            use_m0_with_idx_off
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: use_m0_with_idx_off
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_ON killed $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
@@ -300,20 +370,23 @@ body:             |
 
 ---
 name:            three_in_a_row
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: three_in_a_row
     ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
-    ; GCN-NEXT: $vgpr17 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
+    ; GCN-NEXT: $vgpr17 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: $vgpr18 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
   S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
-  S_SET_GPR_IDX_ON killed $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
-  $vgpr17 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
+  S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+  $vgpr17 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
   S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
   S_SET_GPR_IDX_ON killed $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
   $vgpr18 = V_MOV_B32_indirect_read undef $vgpr0, implicit $exec, implicit $m0, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
@@ -322,11 +395,16 @@ body:             |
 
 ---
 name:            different_gpr_index_then_two_same_indexes
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: different_gpr_index_then_two_same_indexes
-    ; GCN: S_SET_GPR_IDX_ON $sgpr1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr1, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
     ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
@@ -346,11 +424,16 @@ body:             |
 
 ---
 name:            two_same_indexes_then_different
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: two_same_indexes_then_different
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
@@ -370,11 +453,16 @@ body:             |
 
 ---
 name:            indirect_mov
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
 
     ; GCN-LABEL: name: indirect_mov
-    ; GCN: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $m0, implicit-def $mode, implicit undef $m0, implicit $mode
     ; GCN-NEXT: $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: V_MOV_B32_indirect_write undef $vgpr0, undef $vgpr3, implicit $exec, implicit $m0, implicit-def $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3(tied-def 4)
     ; GCN-NEXT: V_MOV_B32_indirect_write undef $vgpr0, undef $vgpr3, implicit $exec, implicit $m0, implicit-def $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed $vgpr0_vgpr1_vgpr2_vgpr3(tied-def 4)
@@ -390,10 +478,15 @@ body:             |
 
 ---
 name:            simple_bundle
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
     ; GCN-LABEL: name: simple_bundle
-    ; GCN: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
     ; GCN-NEXT:   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
     ; GCN-NEXT:   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: }
@@ -415,10 +508,15 @@ body:             |
 
 ---
 name:            salu_in_between_bundle
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
     ; GCN-LABEL: name: salu_in_between_bundle
-    ; GCN: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
     ; GCN-NEXT:   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
     ; GCN-NEXT:   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT: }
@@ -442,10 +540,15 @@ body:             |
 
 ---
 name:            valu_in_between_bundle
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
     ; GCN-LABEL: name: valu_in_between_bundle
-    ; GCN: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
     ; GCN-NEXT:   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
     ; GCN-NEXT:   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT:   S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
@@ -471,10 +574,15 @@ body:             |
 
 ---
 name:            changed_index_bundle
+tracksRegLiveness: true
 body:             |
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
     ; GCN-LABEL: name: changed_index_bundle
-    ; GCN: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
+    ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: BUNDLE implicit-def $m0, implicit-def $m0_lo16, implicit-def $m0_hi16, implicit-def $mode, implicit-def $vgpr16, implicit-def $vgpr16_lo16, implicit-def $vgpr16_hi16, implicit $sgpr2, implicit $m0, implicit $mode, implicit undef $vgpr1, implicit $exec, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 {
     ; GCN-NEXT:   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
     ; GCN-NEXT:   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
     ; GCN-NEXT:   S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
@@ -500,10 +608,12 @@ body:             |
 
 ---
 name:            simple_cbranch_vccz
+tracksRegLiveness: true
 body:             |
   ; GCN-LABEL: name: simple_cbranch_vccz
   ; GCN: bb.0:
   ; GCN-NEXT:   successors: %bb.1(0x80000000)
+  ; GCN-NEXT:   liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
   ; GCN-NEXT: {{  $}}
   ; GCN-NEXT:   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
   ; GCN-NEXT:   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
@@ -513,6 +623,8 @@ body:             |
   ; GCN-NEXT: {{  $}}
   ; GCN-NEXT: bb.1:
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
   S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
@@ -525,10 +637,12 @@ body:             |
 
 ---
 name:            simple_cbranch_execz
+tracksRegLiveness: true
 body:             |
   ; GCN-LABEL: name: simple_cbranch_execz
   ; GCN: bb.0:
   ; GCN-NEXT:   successors:
+  ; GCN-NEXT:   liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
   ; GCN-NEXT: {{  $}}
   ; GCN-NEXT:   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
   ; GCN-NEXT:   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
@@ -537,6 +651,8 @@ body:             |
   ; GCN-NEXT: {{  $}}
   ; GCN-NEXT: bb.1:
   bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $vgpr0, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, $vcc
+
   S_SET_GPR_IDX_ON $sgpr2, 1, implicit-def $mode, implicit-def $m0, implicit $mode, implicit undef $m0
   $vgpr16 = V_MOV_B32_indirect_read undef $vgpr1, implicit $exec, implicit $m0, implicit $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
   S_SET_GPR_IDX_OFF implicit-def $mode, implicit $mode
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
new file mode 100644
index 0000000000000..7f94f55237621
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
@@ -0,0 +1,38 @@
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -run-pass=si-pre-emit-peephole -verify-machineinstrs -o - %s | FileCheck %s
+
+---
+name: fmac_f64_e32_return_copy
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $vgpr0, $vgpr1
+
+    ; CHECK-LABEL: name: fmac_f64_e32_return_copy
+    ; CHECK: $vgpr0_vgpr1 = nofpexcept V_FMA_F64_e64 0, killed $vgpr4_vgpr5, 0, killed $vgpr0_vgpr1, 0, killed $vgpr2_vgpr3, 0, 0, implicit $mode, implicit $exec
+    ; CHECK-NEXT: SI_RETURN implicit killed $vgpr0, implicit killed $vgpr1
+    renamable $vgpr2_vgpr3 = nofpexcept V_RSQ_F64_e32 $vgpr0_vgpr1, implicit $mode, implicit $exec
+    renamable $vgpr4_vgpr5 = nofpexcept V_MUL_F64_e64 0, $vgpr2_vgpr3, 0, $vgpr0_vgpr1, 0, 0, implicit $mode, implicit $exec
+    renamable $vgpr0_vgpr1 = nofpexcept V_FMA_F64_e64 0, killed $vgpr0_vgpr1, 0, $vgpr2_vgpr3, 0, 4602678819172646912, 0, 0, implicit $mode, implicit $exec
+    renamable $vgpr2_vgpr3 = nofpexcept V_FMAC_F64_e32 killed renamable $vgpr4_vgpr5, killed renamable $vgpr0_vgpr1, killed renamable $vgpr2_vgpr3, implicit $mode, implicit $exec
+    $vgpr0 = V_MOV_B32_e32 killed $vgpr2, implicit $exec, implicit $exec
+    $vgpr1 = V_MOV_B32_e32 killed $vgpr3, implicit $exec, implicit $exec
+    SI_RETURN implicit killed $vgpr0, implicit killed $vgpr1
+...
+
+---
+name: fmac_f32_e32_return_copy
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $vgpr0
+
+    ; CHECK-LABEL: name: fmac_f32_e32_return_copy
+    ; CHECK: $vgpr0 = nofpexcept V_FMA_F32_e64 0, killed $vgpr4, 0, killed $vgpr0, 0, killed $vgpr2, 0, 0, implicit $mode, implicit $exec
+    ; CHECK-NEXT: SI_RETURN implicit killed $vgpr0
+    renamable $vgpr2 = nofpexcept V_RSQ_F32_e32 $vgpr0, implicit $exec, implicit $mode
+    renamable $vgpr4 = nofpexcept V_MUL_F32_e64 0, $vgpr2, 0, $vgpr0, 0, 0, implicit $mode, implicit $exec
+    renamable $vgpr0 = nofpexcept V_FMA_F32_e64 0, killed $vgpr0, 0, $vgpr2, 0, 1056964608, 0, 0, implicit $mode, implicit $exec
+    renamable $vgpr2 = nofpexcept V_FMAC_F32_e32 killed renamable $vgpr4, killed renamable $vgpr0, killed renamable $vgpr2, implicit $mode, implicit $exec
+    $vgpr0 = V_MOV_B32_e32 killed $vgpr2, implicit $exec, implicit $exec
+    SI_RETURN implicit killed $vgpr0
+...
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-preserve-loop-info.mir b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-preserve-loop-info.mir
index e3ac9f70a50a0..e225933aee734 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-preserve-loop-info.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-preserve-loop-info.mir
@@ -3,7 +3,9 @@
 # CHECK: Running analysis: MachineLoopAnalysis on vcc_and_removal_preserves_mli
 # CHECK-NEXT: Running analysis: MachineDominatorTreeAnalysis on vcc_and_removal_preserves_mli
 # CHECK-NEXT: Running pass: SIPreEmitPeepholePass on vcc_and_removal_preserves_mli
+# CHECK-NEXT: Running analysis: ReachingDefAnalysis on vcc_and_removal_preserves_mli
 # CHECK-NEXT: Invalidating analysis: MachineDominatorTreeAnalysis on vcc_and_removal_preserves_mli
+# CHECK-NEXT: Invalidating analysis: ReachingDefAnalysis on vcc_and_removal_preserves_mli
 # CHECK-NEXT: Running pass: MachineLoopPrinterPass on vcc_and_removal_preserves_mli
 # CHECK-NEXT: Machine loop info for machine function 'vcc_and_removal_preserves_mli':
 # CHECK-NOT: Running analysis: MachineLoopAnalysis on vcc_and_removal_preserves_mli
@@ -11,12 +13,17 @@
 
 ---
 name: vcc_and_removal_preserves_mli
+tracksRegLiveness: true
 body: |
   bb.0:
+    liveins: $vgpr0
+
     S_BRANCH %bb.1
 
   ; S_AND gets removed
   bb.1:
+    liveins: $vgpr0
+
     V_CMP_EQ_U32_e32 0, $vgpr0, implicit-def $vcc, implicit $exec
     $vcc = S_AND_B64 $exec, $vcc, implicit-def dead $scc
     S_CBRANCH_VCCNZ %bb.1, implicit $vcc
@@ -27,12 +34,14 @@ body: |
 ...
 
 # CHECK-LABEL: Running pass: SIPreEmitPeepholePass on vcc_branch_destroys_loop
+# CHECK-NEXT: Running analysis: ReachingDefAnalysis on vcc_branch_destroys_loop
 # CHECK-NOT: Running analysis: MachineLoopAnalysis on vcc_branch_destroys_loop
 # CHECK: Machine loop info for machine function 'vcc_branch_destroys_loop':
 # CHECK-NOT: Loop at depth
 
 ---
 name: vcc_branch_destroys_loop
+tracksRegLiveness: true
 body: |
   bb.0:
     S_BRANCH %bb.1
diff --git a/llvm/test/CodeGen/AMDGPU/skip-branch-taildup-ret.mir b/llvm/test/CodeGen/AMDGPU/skip-branch-taildup-ret.mir
index 4b5d05167d53a..306a5e56df2f8 100644
--- a/llvm/test/CodeGen/AMDGPU/skip-branch-taildup-ret.mir
+++ b/llvm/test/CodeGen/AMDGPU/skip-branch-taildup-ret.mir
@@ -3,6 +3,7 @@
 
 ---
 name: skip_branch_taildup_endpgm
+tracksRegLiveness: true
 machineFunctionInfo:
   isEntryFunction: true
 body:             |
@@ -124,6 +125,7 @@ body:             |
 
 ---
 name: skip_branch_taildup_ret
+tracksRegLiveness: true
 body:             |
   ; CHECK-LABEL: name: skip_branch_taildup_ret
   ; CHECK: bb.0:

>From eb1d7da1a5058069340c42562b0bf271cdb0497a Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Mon, 6 Jul 2026 08:07:42 -0500
Subject: [PATCH 3/3] Add documentation

Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
 llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp  | 15 ++++++++---
 .../AMDGPU/si-pre-emit-peephole-fmac.mir      | 25 +++++++++++++++++++
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
index 22c6aeec437f8..734ccbad4eb35 100644
--- a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
@@ -83,9 +83,10 @@ class SIPreEmitPeephole {
   void addOperandAndMods(MachineInstrBuilder &NewMI, unsigned SrcMods,
                          bool IsHiBits, const MachineOperand &SrcMO);
 
-  // Delayed post-RA conversion from a two-address instruction to a
-  // three-address instruction. The copy instructions become redundant after
-  // retargeting the converted instruction to NewDst.
+  // Hold information about a candidate for delayed post-RA conversion from a
+  // two-address instruction to a three-address instruction. The copy
+  // instructions become redundant after retargeting the converted instruction
+  // to NewDst.
   struct ThreeAddressCandidate {
     MachineInstr *TwoAddrMI;
     Register NewDst;
@@ -817,10 +818,14 @@ std::optional<Register> SIPreEmitPeephole::checkCopy(MachineInstr &TwoAddress,
     return std::nullopt;
 
   Register Reg = Dst.getReg();
+  // Check that it is safe to define the copy destination register at the
+  // current position of the two-address instruction.
   SmallPtrSet<MachineInstr *, 1> Ignore{&TwoAddress, &MaybeCopy};
   if (!RDI->isSafeToDefRegAt(&TwoAddress, Reg, Ignore))
     return std::nullopt;
 
+  // Check that the two-address instruction and the copy have the same exec
+  // mask.
   if (!RDI->hasSameReachingDef(&TwoAddress, &MaybeCopy, AMDGPU::EXEC))
     return std::nullopt;
 
@@ -846,7 +851,7 @@ Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
   for (Register SubReg : DestRegs) {
     if (!SubReg.isPhysical())
       return Register();
-    if (RDI->isReachingDefLiveOut(&MI, SubReg))
+    if (RDI->getLocalLiveOutMIDef(MI.getParent(), SubReg) == &MI)
       return Register();
 
     SmallPtrSet<MachineInstr *, 1> Uses;
@@ -869,6 +874,8 @@ Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
   if (Replacements.size() == 1)
     return Replacements.front();
 
+  // Try to identify a matching super-register/tuple for the f64 case and abort
+  // the transformation if there is none.
   Register Tuple = TRI->getMatchingSuperReg(Replacements.front(), AMDGPU::sub0,
                                             TRI->getVGPR64Class());
   if (!Tuple)
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
index 7f94f55237621..fc8e9552bbf18 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
@@ -36,3 +36,28 @@ body: |
     $vgpr0 = V_MOV_B32_e32 killed $vgpr2, implicit $exec, implicit $exec
     SI_RETURN implicit killed $vgpr0
 ...
+
+---
+name: fmac_f32_e32_copy_live_out
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $vgpr0, $vgpr2, $vgpr4
+    successors: %bb.1
+
+    ; CHECK-LABEL: name: fmac_f32_e32_copy_live_out
+    ; CHECK: renamable $vgpr2 = nofpexcept V_FMAC_F32_e32 killed $vgpr4, killed $vgpr0, killed $vgpr2, implicit $mode, implicit $exec
+    ; CHECK-NEXT: $vgpr0 = V_MOV_B32_e32 $vgpr2, implicit $exec, implicit $exec
+    ; CHECK-NEXT: S_BRANCH %bb.1
+    renamable $vgpr2 = nofpexcept V_FMAC_F32_e32 killed renamable $vgpr4, killed renamable $vgpr0, killed renamable $vgpr2, implicit $mode, implicit $exec
+    $vgpr0 = V_MOV_B32_e32 $vgpr2, implicit $exec, implicit $exec
+    S_BRANCH %bb.1
+
+  bb.1:
+    liveins: $vgpr2
+
+    ; CHECK: bb.1:
+    ; CHECK-NEXT: liveins: $vgpr2
+    ; CHECK: SI_RETURN implicit killed $vgpr2
+    SI_RETURN implicit killed $vgpr2
+...



More information about the llvm-commits mailing list