[llvm] [AMDGPU] Post-RA Peephole for Two-Address Instructions (PR #207731)
Lukas Sommer via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 02:58:18 PDT 2026
https://github.com/sommerlukas updated https://github.com/llvm/llvm-project/pull/207731
>From 62c946210fa51ac24a74d00bef2f44c4cb1b5221 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/6] 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 650ab3de0d5b2e96328c4c33f4c8f8f35c9021d4 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/6] 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 aedd20ee15283..656bd9363458b 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 22f1013f207e9..b3426c08c8b58 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 27f84ca8e3b5c..518aef23205a3 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 dcf99afd64a54..77e11a45ef910 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 921a4c03ee09b..516c05873b474 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 542af92191f61..195d17d6b05b8 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 a28521c73f247..583fa9c552348 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 e5f0d01a664e3..7c17eaf0d6275 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 d10df2ed1d11f..912a8c8b017b0 100644
--- a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
+++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
@@ -443,6 +443,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
@@ -765,6 +766,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
@@ -1092,6 +1094,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
@@ -1432,6 +1435,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 9a2a8b39f3c02..1defd9b09834e 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 492a0dd2bafe9..b9dab105ab44f 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 096cc33a07c28..f75e512766caf 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 76a7303d9a068..06e4c412d35d4 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 12eff8da0e477..23a3a862696e4 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 c5731f246aa11f16a05630b922e66eda987123cc 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/6] 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
+...
>From 6ce398b91f60122c252e3061a5f6059039bbfce4 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Tue, 7 Jul 2026 07:56:44 -0500
Subject: [PATCH 4/6] Auto-generate test checks
Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
.../AMDGPU/si-pre-emit-peephole-fmac.mir | 39 ++++++++++++++-----
1 file changed, 29 insertions(+), 10 deletions(-)
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 fc8e9552bbf18..d3391e2cda4e3 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
@@ -1,4 +1,5 @@
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -run-pass=si-pre-emit-peephole -verify-machineinstrs -o - %s | FileCheck %s
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -run-pass=si-pre-emit-peephole -o - %s | FileCheck %s
---
name: fmac_f64_e32_return_copy
@@ -8,7 +9,12 @@ body: |
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: liveins: $vgpr0, $vgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $vgpr2_vgpr3 = nofpexcept V_RSQ_F64_e32 $vgpr0_vgpr1, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr4_vgpr5 = nofpexcept V_MUL_F64_e64 0, $vgpr2_vgpr3, 0, $vgpr0_vgpr1, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr0_vgpr1 = nofpexcept V_FMA_F64_e64 0, killed $vgpr0_vgpr1, 0, $vgpr2_vgpr3, 0, 4602678819172646912, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $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
@@ -27,7 +33,12 @@ body: |
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: liveins: $vgpr0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $vgpr2 = nofpexcept V_RSQ_F32_e32 $vgpr0, implicit $exec, implicit $mode
+ ; CHECK-NEXT: renamable $vgpr4 = nofpexcept V_MUL_F32_e64 0, $vgpr2, 0, $vgpr0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr0 = nofpexcept V_FMA_F32_e64 0, killed $vgpr0, 0, $vgpr2, 0, 1056964608, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $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
@@ -41,14 +52,25 @@ body: |
name: fmac_f32_e32_copy_live_out
tracksRegLiveness: true
body: |
+ ; CHECK-LABEL: name: fmac_f32_e32_copy_live_out
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: liveins: $vgpr0, $vgpr2, $vgpr4
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: 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
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: liveins: $vgpr2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: SI_RETURN implicit killed $vgpr2
+ ; Negative test to check the peephole doesn't apply if the original
+ ; destination register is live out of the block.
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
@@ -56,8 +78,5 @@ body: |
bb.1:
liveins: $vgpr2
- ; CHECK: bb.1:
- ; CHECK-NEXT: liveins: $vgpr2
- ; CHECK: SI_RETURN implicit killed $vgpr2
SI_RETURN implicit killed $vgpr2
...
>From 63d75ff5a6732d728ebe964ce5f1273055a8639a Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Wed, 8 Jul 2026 11:22:02 -0500
Subject: [PATCH 5/6] Extend to more copies and opcodes
Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp | 213 ++++++++++++------
llvm/test/CodeGen/AMDGPU/mad-mix.ll | 9 +-
.../AMDGPU/si-pre-emit-peephole-fmac-f16.mir | 41 ++++
.../AMDGPU/si-pre-emit-peephole-fmac.mir | 42 ++++
4 files changed, 225 insertions(+), 80 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac-f16.mir
diff --git a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
index 734ccbad4eb35..ebd5b89e3154f 100644
--- a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
@@ -96,19 +96,26 @@ class SIPreEmitPeephole {
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
+ // Return true if MI is a candidate for late conversion to a three-address
+ // instruction to avoid copies.
+ bool isLateThreeAddrPeepholeCandidate(const MachineInstr &MI) const;
+ // Check if MaybeCopy is a simple copy of Src. If it is a supported
// copy, return the destination register of the copy.
- std::optional<Register> checkCopy(MachineInstr &TwoAddress,
- MachineInstr &MaybeCopy, Register Src);
+ Register checkCopy(MachineInstr &TwoAddress, MachineInstr &MaybeCopy,
+ Register Src, const TargetRegisterClass *NewDstRC);
// 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
+ // replacement and fills Copies with the copy instructions to remove after
// the replacement.
Register
shouldReplaceWithThreeAddress(MachineInstr &MI,
SmallVectorImpl<MachineInstr *> &Copies);
+ // Convert two-adress instruction in Cand to its three-address equivalent,
+ // targeting the register given in Cand.
+ bool convertToThreeAddressInstr(ThreeAddressCandidate &Cand);
+
public:
bool run(MachineFunction &MF, MachineLoopInfo *MLI,
const ReachingDefInfo *RDI);
@@ -795,41 +802,79 @@ 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;
+bool SIPreEmitPeephole::isLateThreeAddrPeepholeCandidate(
+ const MachineInstr &MI) const {
+ // This is a subset of the opcodes that are convertible to three-address
+ // instructions according to . This is intended. For some cases,
+ // convertToThreeAddress could early-clobber, which would require us to roll
+ // back the transformation. However, rollback is not side-effect free for some
+ // cases in convertToThreeAddress that fold immediates. Therefore, we limit
+ // this peephole to only the instructions for which rollback will not be
+ // necessary.
+ switch (MI.getOpcode()) {
+ case AMDGPU::V_MAC_F16_e32:
+ case AMDGPU::V_MAC_F16_e64:
+ case AMDGPU::V_MAC_F32_e32:
+ case AMDGPU::V_MAC_F32_e64:
+ case AMDGPU::V_MAC_LEGACY_F32_e32:
+ case AMDGPU::V_MAC_LEGACY_F32_e64:
+ case AMDGPU::V_FMAC_F16_e32:
+ case AMDGPU::V_FMAC_F16_e64:
+ case AMDGPU::V_FMAC_F16_t16_e64:
+ case AMDGPU::V_FMAC_F16_fake16_e64:
+ case AMDGPU::V_FMAC_F32_e32:
+ case AMDGPU::V_FMAC_F32_e64:
+ case AMDGPU::V_FMAC_LEGACY_F32_e32:
+ case AMDGPU::V_FMAC_LEGACY_F32_e64:
+ case AMDGPU::V_FMAC_F64_e32:
+ case AMDGPU::V_FMAC_F64_e64:
+ return true;
default:
- return std::nullopt;
+ return false;
}
+}
+
+Register SIPreEmitPeephole::checkCopy(MachineInstr &TwoAddress,
+ MachineInstr &MaybeCopy, Register Src,
+ const TargetRegisterClass *NewDstRC) {
+ if (MaybeCopy.isBundle())
+ return Register();
+
+ if (!TII->isFoldableCopy(MaybeCopy) ||
+ MaybeCopy.getOpcode() == AMDGPU::WWM_COPY)
+ return Register();
- MachineOperand CopySrc = MaybeCopy.getOperand(1);
- if (!CopySrc.isReg() || CopySrc.getReg() != Src)
- return std::nullopt;
+ if (TII->hasAnyModifiersSet(MaybeCopy))
+ return Register();
+
+ auto CopySrc = MaybeCopy.getOperand(TII->getFoldableCopySrcIdx(MaybeCopy));
+ if (!CopySrc.isReg() || CopySrc.getReg() != Src ||
+ CopySrc.getSubReg() != AMDGPU::NoSubRegister)
+ return Register();
MachineOperand Dst = MaybeCopy.getOperand(0);
- if (!Dst.isReg())
- return std::nullopt;
+ if (!Dst.isReg() || Dst.getSubReg() != AMDGPU::NoSubRegister)
+ return Register();
+
+ Register DstReg = Dst.getReg();
+ if (TRI->getPhysRegBaseClass(DstReg) != TRI->getPhysRegBaseClass(Src))
+ return Register();
+
+ if (NewDstRC && !NewDstRC->contains(DstReg.asMCReg()))
+ return Register();
- 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;
+ if (!RDI->isSafeToDefRegAt(&TwoAddress, DstReg, Ignore))
+ return Register();
// Check that the two-address instruction and the copy have the same exec
// mask.
if (!RDI->hasSameReachingDef(&TwoAddress, &MaybeCopy, AMDGPU::EXEC))
- return std::nullopt;
+ return Register();
- return Reg;
+ return DstReg;
}
Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
@@ -838,54 +883,96 @@ Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
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())
+ const TargetRegisterClass *NewDstRC =
+ TII->getRegClass(MI.getDesc(), Dst->getOperandNo());
+
+ auto CheckRegisterCopies =
+ [&](Register Reg, const TargetRegisterClass *ReplacementRC) -> Register {
+ if (!Reg.isPhysical())
return Register();
- if (RDI->getLocalLiveOutMIDef(MI.getParent(), SubReg) == &MI)
+ if (RDI->getLocalLiveOutMIDef(MI.getParent(), Reg) == &MI)
return Register();
SmallPtrSet<MachineInstr *, 1> Uses;
- RDI->getReachingLocalUses(&MI, SubReg, Uses);
+ RDI->getReachingLocalUses(&MI, Reg, Uses);
if (Uses.size() != 1)
return Register();
MachineInstr &Use = **Uses.begin();
- std::optional<Register> MaybeRegister = checkCopy(MI, Use, SubReg);
+ Register ReplacementReg = checkCopy(MI, Use, Reg, ReplacementRC);
- if (!MaybeRegister)
+ if (!ReplacementReg)
return Register();
- Replacements.push_back(*MaybeRegister);
+
Copies.push_back(&Use);
- }
+ return ReplacementReg;
+ };
+
+ Register DstReg = Dst->getReg();
+ if (Register Replacement = CheckRegisterCopies(DstReg, NewDstRC))
+ return Replacement;
- if (Replacements.size() > 2)
+ // If we didn't find a copy for the full register, we might be dealing with a
+ // 64-bit register and copies for the individual parts. Check both
+ // subregisters for matching copies.
+ Register Sub0 = TRI->getSubReg(Dst->getReg(), AMDGPU::sub0);
+ Register Sub1 = TRI->getSubReg(Dst->getReg(), AMDGPU::sub1);
+ if (!Sub0 || !Sub1)
return Register();
- if (Replacements.size() == 1)
- return Replacements.front();
+ auto Sub0Replacment = CheckRegisterCopies(Sub0, nullptr);
+ auto Sub1Replacement = CheckRegisterCopies(Sub1, nullptr);
+ if (!Sub0Replacment || !Sub1Replacement)
+ return Register();
// 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 (!NewDstRC)
+ return Register();
+ Register Tuple =
+ TRI->getMatchingSuperReg(Sub0Replacment, AMDGPU::sub0, NewDstRC);
if (!Tuple)
return Register();
- if (TRI->getSubReg(Tuple, AMDGPU::sub1) != Replacements[1].asMCReg())
+ if (TRI->getSubReg(Tuple, AMDGPU::sub1) != Sub1Replacement.asMCReg())
return Register();
return Tuple;
}
+bool SIPreEmitPeephole::convertToThreeAddressInstr(
+ ThreeAddressCandidate &Cand) {
+ MachineInstr *ThreeAddrsInst =
+ TII->convertToThreeAddress(*Cand.TwoAddrMI, nullptr, nullptr);
+ if (!ThreeAddrsInst)
+ return false;
+ MachineOperand &NewDst = ThreeAddrsInst->getOperand(0);
+ assert(NewDst.isReg());
+
+ // The two asserts are defensive for the case that the implementation of
+ // convertToThreeAddress changes in a manner incompatible with this peephole.
+ const TargetRegisterClass *DstRC =
+ TII->getRegClass(ThreeAddrsInst->getDesc(), NewDst.getOperandNo());
+ assert((!DstRC || DstRC->contains(Cand.NewDst.asMCReg())) &&
+ "candidate prechecks should guarantee a legal destination class");
+
+ auto RegistersOverlap = [&](MachineOperand &MO) {
+ if (!MO.isReg())
+ return false;
+ return TRI->regsOverlap(Cand.NewDst, MO.getReg());
+ };
+ assert((!NewDst.isEarlyClobber() ||
+ llvm::none_of(ThreeAddrsInst->uses(), RegistersOverlap)) &&
+ "three-address instruction must not early-clobber the new destination "
+ "register");
+
+ NewDst.setReg(Cand.NewDst);
+ NewDst.setIsRenamable(false);
+ Cand.TwoAddrMI->eraseFromParent();
+ llvm::for_each(Cand.CopiesToRemove,
+ [](MachineInstr *Copy) { Copy->eraseFromParent(); });
+ return true;
+}
+
PreservedAnalyses
llvm::SIPreEmitPeepholePass::run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM) {
@@ -948,9 +1035,7 @@ bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo,
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)
+ if (!isLateThreeAddrPeepholeCandidate(MI))
continue;
SmallVector<MachineInstr *, 2> Copies;
@@ -958,28 +1043,8 @@ bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo,
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;
- }
+ for (ThreeAddressCandidate &Cand : Candidates)
+ Changed |= convertToThreeAddressInstr(Cand);
if (!ST.hasVGPRIndexMode())
continue;
diff --git a/llvm/test/CodeGen/AMDGPU/mad-mix.ll b/llvm/test/CodeGen/AMDGPU/mad-mix.ll
index 4e1acf114da5d..e308216402cc6 100644
--- a/llvm/test/CodeGen/AMDGPU/mad-mix.ll
+++ b/llvm/test/CodeGen/AMDGPU/mad-mix.ll
@@ -299,8 +299,7 @@ define <2 x float> @v_mad_mix_v2f32_shuffle(<2 x half> %src0, <2 x half> %src1,
; GFX9GEN-NEXT: v_cvt_f32_f16_sdwa v2, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9GEN-NEXT: v_cvt_f32_f16_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9GEN-NEXT: v_mad_f32 v0, v3, v0, v2
-; GFX9GEN-NEXT: v_mac_f32_e32 v2, v4, v1
-; GFX9GEN-NEXT: v_mov_b32_e32 v1, v2
+; GFX9GEN-NEXT: v_mad_f32 v1, v4, v1, v2
; GFX9GEN-NEXT: s_setpc_b64 s[30:31]
;
; VI-LABEL: v_mad_mix_v2f32_shuffle:
@@ -312,8 +311,7 @@ define <2 x float> @v_mad_mix_v2f32_shuffle(<2 x half> %src0, <2 x half> %src1,
; VI-NEXT: v_cvt_f32_f16_sdwa v2, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; VI-NEXT: v_cvt_f32_f16_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; VI-NEXT: v_mad_f32 v0, v3, v0, v2
-; VI-NEXT: v_mac_f32_e32 v2, v4, v1
-; VI-NEXT: v_mov_b32_e32 v1, v2
+; VI-NEXT: v_mad_f32 v1, v4, v1, v2
; VI-NEXT: s_setpc_b64 s[30:31]
;
; CI-LABEL: v_mad_mix_v2f32_shuffle:
@@ -445,8 +443,7 @@ define float @v_mad_mix_f32_absf16lo_f16lo_f16lo(half %src0, half %src1, half %s
; SDAG-CI-NEXT: v_cvt_f32_f16_e32 v3, v1
; SDAG-CI-NEXT: v_cvt_f32_f16_e32 v1, v2
; SDAG-CI-NEXT: v_cvt_f32_f16_e64 v0, |v0|
-; SDAG-CI-NEXT: v_mac_f32_e32 v1, v0, v3
-; SDAG-CI-NEXT: v_mov_b32_e32 v0, v1
+; SDAG-CI-NEXT: v_mad_f32 v0, v0, v3, v1
; SDAG-CI-NEXT: s_setpc_b64 s[30:31]
;
; GISEL-CI-LABEL: v_mad_mix_f32_absf16lo_f16lo_f16lo:
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac-f16.mir b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac-f16.mir
new file mode 100644
index 0000000000000..6d49eefb14c32
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac-f16.mir
@@ -0,0 +1,41 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -run-pass=si-pre-emit-peephole -o - %s | FileCheck %s
+
+---
+name: fmac_f16_t16_e64_return_copy
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $vgpr1_lo16, $vgpr2_lo16, $vgpr4_lo16
+
+ ; CHECK-LABEL: name: fmac_f16_t16_e64_return_copy
+ ; CHECK: liveins: $vgpr1_lo16, $vgpr2_lo16, $vgpr4_lo16
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e64 0, $vgpr1_lo16, 0, implicit $exec
+ ; CHECK-NEXT: $vgpr0_lo16 = nofpexcept V_FMA_F16_gfx9_t16_e64 0, $vgpr4_lo16, 0, $vgpr1_lo16, 0, killed $vgpr2_lo16, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed $vgpr0_lo16
+ $vgpr0_lo16 = V_MOV_B16_t16_e64 0, $vgpr1_lo16, 0, implicit $exec
+ $vgpr2_lo16 = nofpexcept V_FMAC_F16_t16_e64 0, $vgpr4_lo16, 0, $vgpr1_lo16, 0, killed $vgpr2_lo16, 0, 0, 0, implicit $mode, implicit $exec
+ $vgpr0_lo16 = V_MOV_B16_t16_e64 0, killed $vgpr2_lo16, 0, implicit $exec
+ S_ENDPGM 0, implicit killed $vgpr0_lo16
+...
+
+---
+name: fmac_f16_t16_e64_return_copy_with_modifier
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $vgpr1_lo16, $vgpr2_lo16, $vgpr4_lo16
+
+ ; CHECK-LABEL: name: fmac_f16_t16_e64_return_copy_with_modifier
+ ; CHECK: liveins: $vgpr1_lo16, $vgpr2_lo16, $vgpr4_lo16
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e64 0, $vgpr1_lo16, 0, implicit $exec
+ ; CHECK-NEXT: $vgpr2_lo16 = nofpexcept V_FMAC_F16_t16_e64 0, $vgpr4_lo16, 0, $vgpr1_lo16, 0, killed $vgpr2_lo16, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e64 1, killed $vgpr2_lo16, 0, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed $vgpr0_lo16
+ $vgpr0_lo16 = V_MOV_B16_t16_e64 0, $vgpr1_lo16, 0, implicit $exec
+ $vgpr2_lo16 = nofpexcept V_FMAC_F16_t16_e64 0, $vgpr4_lo16, 0, $vgpr1_lo16, 0, killed $vgpr2_lo16, 0, 0, 0, implicit $mode, implicit $exec
+ $vgpr0_lo16 = V_MOV_B16_t16_e64 1, killed $vgpr2_lo16, 0, implicit $exec
+ S_ENDPGM 0, implicit killed $vgpr0_lo16
+...
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 d3391e2cda4e3..d900d3f1fa8e1 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
@@ -25,6 +25,29 @@ body: |
SI_RETURN implicit killed $vgpr0, implicit killed $vgpr1
...
+---
+name: fmac_f64_e32_return_full_copy
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $vgpr0, $vgpr1
+
+ ; CHECK-LABEL: name: fmac_f64_e32_return_full_copy
+ ; CHECK: liveins: $vgpr0, $vgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $vgpr2_vgpr3 = nofpexcept V_RSQ_F64_e32 $vgpr0_vgpr1, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr4_vgpr5 = nofpexcept V_MUL_F64_e64 0, $vgpr2_vgpr3, 0, $vgpr0_vgpr1, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr0_vgpr1 = nofpexcept V_FMA_F64_e64 0, killed $vgpr0_vgpr1, 0, $vgpr2_vgpr3, 0, 4602678819172646912, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $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_vgpr1 = V_MOV_B64_e32 killed $vgpr2_vgpr3, implicit $exec, implicit $exec
+ SI_RETURN implicit killed $vgpr0, implicit killed $vgpr1
+...
+
---
name: fmac_f32_e32_return_copy
tracksRegLiveness: true
@@ -48,6 +71,25 @@ body: |
SI_RETURN implicit killed $vgpr0
...
+---
+name: mac_f32_e32_return_copy
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $vgpr0, $vgpr2, $vgpr4
+
+ ; CHECK-LABEL: name: mac_f32_e32_return_copy
+ ; CHECK: liveins: $vgpr0, $vgpr2, $vgpr4
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $vgpr1 = V_MOV_B32_e32 $vgpr0, implicit $exec
+ ; CHECK-NEXT: $vgpr1 = nofpexcept V_MAD_F32_e64 0, killed $vgpr4, 0, killed $vgpr0, 0, killed $vgpr2, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed $vgpr1
+ $vgpr1 = V_MOV_B32_e32 $vgpr0, implicit $exec
+ $vgpr2 = nofpexcept V_MAC_F32_e32 killed $vgpr4, killed $vgpr0, killed $vgpr2, implicit $mode, implicit $exec
+ $vgpr1 = V_MOV_B32_e32 killed $vgpr2, implicit $exec
+ S_ENDPGM 0, implicit killed $vgpr1
+...
+
---
name: fmac_f32_e32_copy_live_out
tracksRegLiveness: true
>From 81dc2f44f2417796d37445ea221d20e34242f841 Mon Sep 17 00:00:00 2001
From: Lukas Sommer <lukas.sommer at amd.com>
Date: Wed, 15 Jul 2026 04:56:57 -0500
Subject: [PATCH 6/6] Address PR feedback
Signed-off-by: Lukas Sommer <lukas.sommer at amd.com>
---
llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp | 49 +++++++++++--------
.../AMDGPU/si-pre-emit-peephole-fmac.mir | 43 ++++++++++++++++
2 files changed, 71 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
index ebd5b89e3154f..c13139b656cc8 100644
--- a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
@@ -96,13 +96,19 @@ class SIPreEmitPeephole {
ArrayRef<MachineInstr *> Copies)
: TwoAddrMI(&TwoAddrMI), NewDst(NewDst), CopiesToRemove(Copies) {}
};
+
// Return true if MI is a candidate for late conversion to a three-address
// instruction to avoid copies.
bool isLateThreeAddrPeepholeCandidate(const MachineInstr &MI) const;
- // Check if MaybeCopy is a simple copy of Src. If it is a supported
- // copy, return the destination register of the copy.
+
+ // Check if MaybeCopy is a simple copy of Src. If NewDstRC is non-null, also
+ // require the copy destination to belong to that register class. The class
+ // check is omitted for copies of individual subregisters; their reconstructed
+ // super-register is checked against the destination class by the caller.
+ // Return the destination register of a supported copy.
Register checkCopy(MachineInstr &TwoAddress, MachineInstr &MaybeCopy,
Register Src, const TargetRegisterClass *NewDstRC);
+
// 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
@@ -804,13 +810,13 @@ MachineInstrBuilder SIPreEmitPeephole::createUnpackedMI(MachineInstr &I,
bool SIPreEmitPeephole::isLateThreeAddrPeepholeCandidate(
const MachineInstr &MI) const {
- // This is a subset of the opcodes that are convertible to three-address
- // instructions according to . This is intended. For some cases,
- // convertToThreeAddress could early-clobber, which would require us to roll
- // back the transformation. However, rollback is not side-effect free for some
- // cases in convertToThreeAddress that fold immediates. Therefore, we limit
- // this peephole to only the instructions for which rollback will not be
- // necessary.
+ // This is only a subset of the opcodes that are convertible to three-address
+ // instructions according to MachineInstr::isConvertibleTo3Addr. This is
+ // intended. For some cases, convertToThreeAddress could early-clobber, which
+ // would require us to roll back the transformation. However, rollback is not
+ // side-effect free for some cases in convertToThreeAddress that fold
+ // immediates. Therefore, we limit this peephole to only the instructions for
+ // which rollback will not be necessary.
switch (MI.getOpcode()) {
case AMDGPU::V_MAC_F16_e32:
case AMDGPU::V_MAC_F16_e64:
@@ -847,12 +853,13 @@ Register SIPreEmitPeephole::checkCopy(MachineInstr &TwoAddress,
if (TII->hasAnyModifiersSet(MaybeCopy))
return Register();
- auto CopySrc = MaybeCopy.getOperand(TII->getFoldableCopySrcIdx(MaybeCopy));
+ MachineOperand &CopySrc =
+ MaybeCopy.getOperand(TII->getFoldableCopySrcIdx(MaybeCopy));
if (!CopySrc.isReg() || CopySrc.getReg() != Src ||
CopySrc.getSubReg() != AMDGPU::NoSubRegister)
return Register();
- MachineOperand Dst = MaybeCopy.getOperand(0);
+ MachineOperand &Dst = MaybeCopy.getOperand(0);
if (!Dst.isReg() || Dst.getSubReg() != AMDGPU::NoSubRegister)
return Register();
@@ -860,18 +867,18 @@ Register SIPreEmitPeephole::checkCopy(MachineInstr &TwoAddress,
if (TRI->getPhysRegBaseClass(DstReg) != TRI->getPhysRegBaseClass(Src))
return Register();
- if (NewDstRC && !NewDstRC->contains(DstReg.asMCReg()))
+ if (NewDstRC && !NewDstRC->contains(DstReg))
return Register();
// 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};
+ SmallPtrSet<MachineInstr *, 2> Ignore{&TwoAddress, &MaybeCopy};
if (!RDI->isSafeToDefRegAt(&TwoAddress, DstReg, Ignore))
return Register();
// Check that the two-address instruction and the copy have the same exec
// mask.
- if (!RDI->hasSameReachingDef(&TwoAddress, &MaybeCopy, AMDGPU::EXEC))
+ if (!RDI->hasSameReachingDef(&TwoAddress, &MaybeCopy, TRI->getExec()))
return Register();
return DstReg;
@@ -920,9 +927,9 @@ Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
if (!Sub0 || !Sub1)
return Register();
- auto Sub0Replacment = CheckRegisterCopies(Sub0, nullptr);
- auto Sub1Replacement = CheckRegisterCopies(Sub1, nullptr);
- if (!Sub0Replacment || !Sub1Replacement)
+ Register Sub0Replacement = CheckRegisterCopies(Sub0, nullptr);
+ Register Sub1Replacement = CheckRegisterCopies(Sub1, nullptr);
+ if (!Sub0Replacement || !Sub1Replacement)
return Register();
// Try to identify a matching super-register/tuple for the f64 case and abort
@@ -930,11 +937,11 @@ Register SIPreEmitPeephole::shouldReplaceWithThreeAddress(
if (!NewDstRC)
return Register();
Register Tuple =
- TRI->getMatchingSuperReg(Sub0Replacment, AMDGPU::sub0, NewDstRC);
+ TRI->getMatchingSuperReg(Sub0Replacement, AMDGPU::sub0, NewDstRC);
if (!Tuple)
return Register();
- if (TRI->getSubReg(Tuple, AMDGPU::sub1) != Sub1Replacement.asMCReg())
+ if (Register(TRI->getSubReg(Tuple, AMDGPU::sub1)) != Sub1Replacement)
return Register();
return Tuple;
}
@@ -952,7 +959,7 @@ bool SIPreEmitPeephole::convertToThreeAddressInstr(
// convertToThreeAddress changes in a manner incompatible with this peephole.
const TargetRegisterClass *DstRC =
TII->getRegClass(ThreeAddrsInst->getDesc(), NewDst.getOperandNo());
- assert((!DstRC || DstRC->contains(Cand.NewDst.asMCReg())) &&
+ assert((!DstRC || DstRC->contains(Cand.NewDst)) &&
"candidate prechecks should guarantee a legal destination class");
auto RegistersOverlap = [&](MachineOperand &MO) {
@@ -1031,7 +1038,7 @@ bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo,
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())) {
+ for (MachineInstr &MI : MBB.instrs()) {
if (MI.isBundle())
continue;
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 d900d3f1fa8e1..f68d89db6f987 100644
--- a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-fmac.mir
@@ -48,6 +48,49 @@ body: |
SI_RETURN implicit killed $vgpr0, implicit killed $vgpr1
...
+---
+name: fmac_f64_e32_return_copy_odd_destination
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8, $vgpr9
+
+ ; The copied halves form an odd-start tuple, which is not in the aligned
+ ; destination register class.
+ ; CHECK-LABEL: name: fmac_f64_e32_return_copy_odd_destination
+ ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8, $vgpr9
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $vgpr6_vgpr7 = nofpexcept V_FMAC_F64_e32 killed $vgpr4_vgpr5, killed $vgpr8_vgpr9, killed $vgpr6_vgpr7, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $vgpr1 = V_MOV_B32_e32 killed $vgpr6, implicit $exec, implicit $exec
+ ; CHECK-NEXT: $vgpr2 = V_MOV_B32_e32 killed $vgpr7, implicit $exec, implicit $exec
+ ; CHECK-NEXT: SI_RETURN implicit killed $vgpr1, implicit killed $vgpr2
+ renamable $vgpr6_vgpr7 = nofpexcept V_FMAC_F64_e32 killed renamable $vgpr4_vgpr5, killed renamable $vgpr8_vgpr9, killed renamable $vgpr6_vgpr7, implicit $mode, implicit $exec
+ $vgpr1 = V_MOV_B32_e32 killed $vgpr6, implicit $exec, implicit $exec
+ $vgpr2 = V_MOV_B32_e32 killed $vgpr7, implicit $exec, implicit $exec
+ SI_RETURN implicit killed $vgpr1, implicit killed $vgpr2
+...
+
+---
+name: fmac_f64_e32_return_copy_non_tuple
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8, $vgpr9
+
+ ; The copied halves are not subregisters of the same 64-bit tuple.
+ ; CHECK-LABEL: name: fmac_f64_e32_return_copy_non_tuple
+ ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8, $vgpr9
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $vgpr6_vgpr7 = nofpexcept V_FMAC_F64_e32 killed $vgpr4_vgpr5, killed $vgpr8_vgpr9, killed $vgpr6_vgpr7, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $vgpr1 = V_MOV_B32_e32 killed $vgpr6, implicit $exec, implicit $exec
+ ; CHECK-NEXT: $vgpr3 = V_MOV_B32_e32 killed $vgpr7, implicit $exec, implicit $exec
+ ; CHECK-NEXT: SI_RETURN implicit killed $vgpr1, implicit killed $vgpr3
+ renamable $vgpr6_vgpr7 = nofpexcept V_FMAC_F64_e32 killed renamable $vgpr4_vgpr5, killed renamable $vgpr8_vgpr9, killed renamable $vgpr6_vgpr7, implicit $mode, implicit $exec
+ $vgpr1 = V_MOV_B32_e32 killed $vgpr6, implicit $exec, implicit $exec
+ $vgpr3 = V_MOV_B32_e32 killed $vgpr7, implicit $exec, implicit $exec
+ SI_RETURN implicit killed $vgpr1, implicit killed $vgpr3
+...
+
---
name: fmac_f32_e32_return_copy
tracksRegLiveness: true
More information about the llvm-commits
mailing list