[llvm] [AMDGPU][True16][MC] Support v_swap_b16. (PR #100442)

Brox Chen via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 24 13:29:57 PDT 2024


https://github.com/broxigarchen updated https://github.com/llvm/llvm-project/pull/100442

>From 7bf65d785cdd007b3cb7b7cfeab160bc28eb9053 Mon Sep 17 00:00:00 2001
From: Ivan Kosarev <ivan.kosarev at amd.com>
Date: Mon, 30 Jan 2023 15:04:07 +0000
Subject: [PATCH 1/3] [True16][MC] Support v_swap_b16.

---
 llvm/lib/Target/AMDGPU/SIInstrFormats.td         |  6 ++++++
 llvm/lib/Target/AMDGPU/VOP1Instructions.td       | 16 +++++++++++++++-
 llvm/test/MC/AMDGPU/gfx10_unsupported.s          |  3 +++
 llvm/test/MC/AMDGPU/gfx11_asm_vop1.s             |  9 +++++++++
 llvm/test/MC/AMDGPU/gfx11_asm_vop1_t16_err.s     | 12 ++++++++++++
 llvm/test/MC/Disassembler/AMDGPU/decode-err.txt  |  9 +++++++++
 .../MC/Disassembler/AMDGPU/gfx11_dasm_vop1.txt   |  6 ++++++
 7 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/SIInstrFormats.td b/llvm/lib/Target/AMDGPU/SIInstrFormats.td
index 1fe8beafd5e5d..9b506eb0a711a 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrFormats.td
+++ b/llvm/lib/Target/AMDGPU/SIInstrFormats.td
@@ -321,6 +321,12 @@ def VOPDstOperand_t16Lo128 : VOPDstOperand <VGPR_16_Lo128> {
   let DecoderMethod = "DecodeVGPR_16_Lo128RegisterClass";
 }
 
+// Source-encoded destination operand for instructions like v_swap_b16.
+def VOPSrcEncodedDstOperand_t16Lo128 : VOPDstOperand <VGPR_16_Lo128> {
+  let EncoderMethod = VSrcT_b16_Lo128.EncoderMethod;
+  let DecoderMethod = VSrcT_b16_Lo128.DecoderMethod;
+}
+
 class VINTRPe <bits<2> op> : Enc32 {
   bits<8> vdst;
   bits<8> vsrc;
diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td
index 2c0d61ee4afa1..d497ef6bbe6f8 100644
--- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td
+++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td
@@ -729,7 +729,20 @@ def V_ACCVGPR_MOV_B32 : VOP1_Pseudo<"v_accvgpr_mov_b32", VOPProfileAccMov, [], 1
   let isAsCheapAsAMove = 1;
 }
 
+def VOP_SWAP_I16 : VOPProfile_True16<VOP_I16_I16> {
+  let Outs32 = (outs VOPDstOperand_t16Lo128:$vdst,
+                     VOPSrcEncodedDstOperand_t16Lo128:$vdst1);
+  let Ins32 = (ins VOPSrcEncodedDstOperand_t16Lo128:$src0,
+                   VOPDstOperand_t16Lo128:$src1);
+  let Asm32 = " $vdst, $src0";
+}
+
 let SubtargetPredicate = isGFX11Plus in {
+  def V_SWAP_B16 : VOP1_Pseudo<"v_swap_b16", VOP_SWAP_I16, [], /* VOP1Only= */ 1> {
+    let Constraints = "$vdst = $src1, $vdst1 = $src0";
+    let DisableEncoding = "$vdst1, $src1";
+    let SchedRW = [Write64Bit, Write64Bit];
+  }
   // Restrict src0 to be VGPR
   def V_PERMLANE64_B32 : VOP1_Pseudo<"v_permlane64_b32", VOP_MOVRELS,
                                       [], /*VOP1Only=*/ 1> {
@@ -952,7 +965,8 @@ defm V_CTZ_I32_B32         : VOP1_Real_FULL_with_name_gfx11_gfx12<0x03a,
   "V_FFBL_B32", "v_ctz_i32_b32">;
 defm V_CLS_I32             : VOP1_Real_FULL_with_name_gfx11_gfx12<0x03b,
   "V_FFBH_I32", "v_cls_i32">;
-defm V_PERMLANE64_B32      : VOP1Only_Real_gfx11_gfx12<0x067>;
+defm V_SWAP_B16              : VOP1Only_Real_gfx11_gfx12<0x066>;
+defm V_PERMLANE64_B32        : VOP1Only_Real_gfx11_gfx12<0x067>;
 defm V_MOV_B16_t16           : VOP1_Real_FULL_t16_gfx11_gfx12<0x01c, "v_mov_b16">;
 defm V_NOT_B16_fake16        : VOP1_Real_FULL_t16_gfx11_gfx12<0x069, "v_not_b16">;
 defm V_CVT_I32_I16_fake16    : VOP1_Real_FULL_t16_gfx11_gfx12<0x06a, "v_cvt_i32_i16">;
diff --git a/llvm/test/MC/AMDGPU/gfx10_unsupported.s b/llvm/test/MC/AMDGPU/gfx10_unsupported.s
index 46b4e6ffb4037..1374417ac354b 100644
--- a/llvm/test/MC/AMDGPU/gfx10_unsupported.s
+++ b/llvm/test/MC/AMDGPU/gfx10_unsupported.s
@@ -3287,6 +3287,9 @@ v_subrev_u32_e64 v255, s[12:13], v1, v2
 v_subrev_u32_sdwa v1, vcc, v2, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:BYTE_2
 // CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
 
+v_swap_b16 v0.l, v0.l
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
 v_wmma_bf16_16x16x16_bf16 v[16:19], 1.0, v[8:15], v[16:19]
 // CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
 
diff --git a/llvm/test/MC/AMDGPU/gfx11_asm_vop1.s b/llvm/test/MC/AMDGPU/gfx11_asm_vop1.s
index d95ef6f15e48d..90d5ca7f72751 100644
--- a/llvm/test/MC/AMDGPU/gfx11_asm_vop1.s
+++ b/llvm/test/MC/AMDGPU/gfx11_asm_vop1.s
@@ -3448,6 +3448,15 @@ v_sqrt_f64 v[5:6], src_scc
 v_sqrt_f64 v[254:255], 0xaf123456
 // GFX11: encoding: [0xff,0x68,0xfc,0x7f,0x56,0x34,0x12,0xaf]
 
+v_swap_b16 v5.l, v1.h
+// GFX11: encoding: [0x81,0xcd,0x0a,0x7e]
+
+v_swap_b16 v5.h, v1.l
+// GFX11: encoding: [0x01,0xcd,0x0a,0x7f]
+
+v_swap_b16 v127.l, v127.l
+// GFX11: encoding: [0x7f,0xcd,0xfe,0x7e]
+
 v_swap_b32 v5, v1
 // GFX11: encoding: [0x01,0xcb,0x0a,0x7e]
 
diff --git a/llvm/test/MC/AMDGPU/gfx11_asm_vop1_t16_err.s b/llvm/test/MC/AMDGPU/gfx11_asm_vop1_t16_err.s
index 5b5381b752feb..ab587a524fc6e 100644
--- a/llvm/test/MC/AMDGPU/gfx11_asm_vop1_t16_err.s
+++ b/llvm/test/MC/AMDGPU/gfx11_asm_vop1_t16_err.s
@@ -211,6 +211,18 @@ v_sqrt_f16_e32 v255.l, v1.l
 v_sqrt_f16_e32 v5.l, v199.l
 // GFX11: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
 
+v_swap_b16_e32 v128.l, v0.l
+// GFX11: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+v_swap_b16_e32 v0.l, s0
+// GFX11: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+v_swap_b16_e32 v0.l, 0
+// GFX11: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+v_swap_b16_e32 v0.l, 0xfe0b
+// GFX11: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
 v_trunc_f16_e32 v128, 0xfe0b
 // GFX11: :[[@LINE-1]]:{{[0-9]+}}: error: operands are not valid for this GPU or mode
 
diff --git a/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt b/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt
index f6d2a19326e1d..c15b65728b247 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt
@@ -19,6 +19,15 @@
 # W64: [[@LINE+1]]:1: warning: invalid instruction encoding
 0xff,0x04,0x02,0xc9,0x03,0x03,0x06,0x05,0x56,0x34,0x12,0xaf
 
+# GFX11: v_swap_b16 v5.h, s1/*Invalid register, operand has 'VGPR_16_Lo128' register class*/ ; encoding: [0x01,0xcc,0x0a,0x7f]
+0x01,0xcc,0x0a,0x7f
+
+# GFX11: v_swap_b16 v5.h, 0x3c00/*Invalid immediate*/ ; encoding: [0x00,0xcc,0x0a,0x7f]
+0xf2,0xcc,0x0a,0x7f
+
+# GFX11: v_swap_b16 v5.h, 0x78563412/*Invalid immediate*/ ; encoding: [0x12,0xcc,0x0a,0x7f]
+0xff,0xcc,0x0a,0x7f,0x12,0x34,0x56,0x78
+
 # W32: v_wmma_f32_16x16x16_f16 v[16:23], v[0:7], v[8:15], v[16:23] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0x42,0x1c]
 # W64: v_wmma_f32_16x16x16_f16 v[16:19], v[0:7], v[8:15], v[16:19] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0x42,0x1c]
 0x10,0x40,0x40,0xcc,0x00,0x11,0x42,0x1c
diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vop1.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vop1.txt
index b176a57d70f86..778f7deb4ec1a 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vop1.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vop1.txt
@@ -3344,6 +3344,12 @@
 # GFX11: v_sqrt_f64_e32 v[254:255], 0xaf123456   ; encoding: [0xff,0x68,0xfc,0x7f,0x56,0x34,0x12,0xaf]
 0xff,0x68,0xfc,0x7f,0x56,0x34,0x12,0xaf
 
+# GFX11: v_swap_b16 v5.l, v1.h                   ; encoding: [0x81,0xcd,0x0a,0x7e]
+0x81,0xcd,0x0a,0x7e
+
+# GFX11: v_swap_b16 v5.h, v1.l                   ; encoding: [0x01,0xcd,0x0a,0x7f]
+0x01,0xcd,0x0a,0x7f
+
 # GFX11: v_swap_b32 v5, v1                       ; encoding: [0x01,0xcb,0x0a,0x7e]
 0x01,0xcb,0x0a,0x7e
 

>From 6e732d441d6d11d6e2c3756539cb52ca7ada1de8 Mon Sep 17 00:00:00 2001
From: Ivan Kosarev <ivan.kosarev at amd.com>
Date: Thu, 16 Feb 2023 15:02:02 +0000
Subject: [PATCH 2/3] [AMDGPU][True16] Match v_swap_b16.

---
 .../Target/AMDGPU/SIShrinkInstructions.cpp    |  56 ++-
 llvm/test/CodeGen/AMDGPU/v_swap_b16.ll        |  39 ++
 llvm/test/CodeGen/AMDGPU/v_swap_b16.mir       | 386 ++++++++++++++++++
 3 files changed, 464 insertions(+), 17 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/v_swap_b16.ll
 create mode 100644 llvm/test/CodeGen/AMDGPU/v_swap_b16.mir

diff --git a/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp b/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp
index 79bcf5e8cd30d..cac381657f6be 100644
--- a/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp
+++ b/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp
@@ -657,6 +657,7 @@ void SIShrinkInstructions::dropInstructionKeepingImpDefs(
 // although requirements match the pass placement and it reduces code size too.
 MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
   assert(MovT.getOpcode() == AMDGPU::V_MOV_B32_e32 ||
+         MovT.getOpcode() == AMDGPU::V_MOV_B16_t16_e32 ||
          MovT.getOpcode() == AMDGPU::COPY);
 
   Register T = MovT.getOperand(0).getReg();
@@ -668,7 +669,12 @@ MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
   Register X = Xop.getReg();
   unsigned Xsub = Xop.getSubReg();
 
-  unsigned Size = TII->getOpSize(MovT, 0) / 4;
+  unsigned Size = TII->getOpSize(MovT, 0);
+
+  // We can't match v_swap_b16 pre-RA, because VGPR_16_Lo128 registers
+  // are not allocatable.
+  if (Size == 2 && X.isVirtual())
+    return nullptr;
 
   if (!TRI->isVGPR(*MRI, X))
     return nullptr;
@@ -684,6 +690,7 @@ MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
     KilledT = MovY->killsRegister(T, TRI);
 
     if ((MovY->getOpcode() != AMDGPU::V_MOV_B32_e32 &&
+         MovY->getOpcode() != AMDGPU::V_MOV_B16_t16_e32 &&
          MovY->getOpcode() != AMDGPU::COPY) ||
         !MovY->getOperand(1).isReg()        ||
         MovY->getOperand(1).getReg() != T   ||
@@ -714,6 +721,7 @@ MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
       }
       if (MovX ||
           (I->getOpcode() != AMDGPU::V_MOV_B32_e32 &&
+           I->getOpcode() != AMDGPU::V_MOV_B16_t16_e32 &&
            I->getOpcode() != AMDGPU::COPY) ||
           I->getOperand(0).getReg() != X ||
           I->getOperand(0).getSubReg() != Xsub) {
@@ -721,7 +729,7 @@ MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
         break;
       }
 
-      if (Size > 1 && (I->getNumImplicitOperands() > (I->isCopy() ? 0U : 1U)))
+      if (Size > 4 && I->getNumImplicitOperands() > (I->isCopy() ? 0U : 1U))
         continue;
 
       MovX = &*I;
@@ -730,23 +738,36 @@ MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
     if (!MovX)
       continue;
 
-    LLVM_DEBUG(dbgs() << "Matched v_swap_b32:\n" << MovT << *MovX << *MovY);
+    LLVM_DEBUG(dbgs() << "Matched v_swap:\n" << MovT << *MovX << *MovY);
 
-    for (unsigned I = 0; I < Size; ++I) {
-      TargetInstrInfo::RegSubRegPair X1, Y1;
-      X1 = getSubRegForIndex(X, Xsub, I);
-      Y1 = getSubRegForIndex(Y, Ysub, I);
-      MachineBasicBlock &MBB = *MovT.getParent();
+    MachineBasicBlock &MBB = *MovT.getParent();
+    SmallVector<MachineInstr*, 4> Swaps;
+    if (Size == 2) {
       auto MIB = BuildMI(MBB, MovX->getIterator(), MovT.getDebugLoc(),
-                         TII->get(AMDGPU::V_SWAP_B32))
-        .addDef(X1.Reg, 0, X1.SubReg)
-        .addDef(Y1.Reg, 0, Y1.SubReg)
-        .addReg(Y1.Reg, 0, Y1.SubReg)
-        .addReg(X1.Reg, 0, X1.SubReg).getInstr();
-      if (MovX->hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
-        // Drop implicit EXEC.
-        MIB->removeOperand(MIB->getNumExplicitOperands());
-        MIB->copyImplicitOps(*MBB.getParent(), *MovX);
+                         TII->get(AMDGPU::V_SWAP_B16))
+        .addDef(X).addDef(Y)
+        .addReg(Y).addReg(X).getInstr();
+      Swaps.push_back(MIB);
+    } else {
+      assert(Size > 0 && Size % 4 == 0);
+      for (unsigned I = 0; I < Size / 4; ++I) {
+        TargetInstrInfo::RegSubRegPair X1, Y1;
+        X1 = getSubRegForIndex(X, Xsub, I);
+        Y1 = getSubRegForIndex(Y, Ysub, I);
+        auto MIB = BuildMI(MBB, MovX->getIterator(), MovT.getDebugLoc(),
+                           TII->get(AMDGPU::V_SWAP_B32))
+          .addDef(X1.Reg, 0, X1.SubReg)
+          .addDef(Y1.Reg, 0, Y1.SubReg)
+          .addReg(Y1.Reg, 0, Y1.SubReg)
+          .addReg(X1.Reg, 0, X1.SubReg).getInstr();
+        Swaps.push_back(MIB);
+      }
+    }
+    // Drop implicit EXEC.
+    if (MovX->hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
+      for (MachineInstr *Swap : Swaps) {
+        Swap->removeOperand(Swap->getNumExplicitOperands());
+        Swap->copyImplicitOps(*MBB.getParent(), *MovX);
       }
     }
     MovX->eraseFromParent();
@@ -833,6 +854,7 @@ bool SIShrinkInstructions::runOnMachineFunction(MachineFunction &MF) {
       }
 
       if (ST->hasSwap() && (MI.getOpcode() == AMDGPU::V_MOV_B32_e32 ||
+                            MI.getOpcode() == AMDGPU::V_MOV_B16_t16_e32 ||
                             MI.getOpcode() == AMDGPU::COPY)) {
         if (auto *NextMI = matchSwap(MI)) {
           Next = NextMI->getIterator();
diff --git a/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll b/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll
new file mode 100644
index 0000000000000..fa8c39f367694
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -march=amdgcn -mcpu=gfx1100 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX11 %s
+
+define half @swap(half %a, half %b, i32 %i) {
+; GFX11-LABEL: swap:
+; GFX11:       ; %bb.0: ; %entry
+; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX11-NEXT:    s_waitcnt_vscnt null, 0x0
+; GFX11-NEXT:    s_mov_b32 s0, 0
+; GFX11-NEXT:  .LBB0_1: ; %loop
+; GFX11-NEXT:    ; =>This Inner Loop Header: Depth=1
+; GFX11-NEXT:    v_add_nc_u32_e32 v2, -1, v2
+; GFX11-NEXT:    v_mov_b16_e32 v0.h, v1.l
+; GFX11-NEXT:    v_swap_b16 v1.l, v0.l
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_3) | instskip(SKIP_1) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT:    v_cmp_eq_u32_e32 vcc_lo, 0, v2
+; GFX11-NEXT:    s_or_b32 s0, vcc_lo, s0
+; GFX11-NEXT:    s_and_not1_b32 exec_lo, exec_lo, s0
+; GFX11-NEXT:    s_cbranch_execnz .LBB0_1
+; GFX11-NEXT:  ; %bb.2: ; %ret
+; GFX11-NEXT:    s_or_b32 exec_lo, exec_lo, s0
+; GFX11-NEXT:    v_mov_b16_e32 v0.l, v1.l
+; GFX11-NEXT:    s_setpc_b64 s[30:31]
+entry:
+  br label %loop
+
+loop:
+  %x = phi half [%a, %entry], [%y, %loop]
+  %y = phi half [%b, %entry], [%x, %loop]
+  %i2 = phi i32 [%i, %entry], [%i3, %loop]
+
+  %i3 = sub i32 %i2, 1
+
+  %cmp = icmp eq i32 %i3, 0
+  br i1 %cmp, label %ret, label %loop
+
+ret:
+  ret half %x
+}
diff --git a/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir b/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir
new file mode 100644
index 0000000000000..28d4b39ad7b04
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir
@@ -0,0 +1,386 @@
+# RUN: llc -simplify-mir -march=amdgcn -mcpu=gfx1100 -run-pass=si-shrink-instructions -verify-machineinstrs %s -o - | FileCheck -check-prefix=GCN %s
+
+# GCN-LABEL: name: swap_phys_condensed
+# GCN: bb.0:
+# GCN-NEXT: liveins:
+# GCN-NEXT: {{^[ ]*$}}
+# GCN-NEXT: $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+# GCN-NEXT: S_SETPC_B64_return
+---
+name:            swap_phys_condensed
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: swap_phys_sparse
+# GCN: bb.0:
+# GCN-NEXT: liveins:
+# GCN-NEXT: {{^[ ]*$}}
+# GCN-NEXT: $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec
+# GCN-NEXT: S_SETPC_B64_return
+---
+name:            swap_phys_sparse
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $vgpr4_lo16, $vgpr6_lo16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: swap_phys_liveout
+# GCN: bb.0:
+# GCN-NEXT: liveins:
+# GCN-NEXT: {{^[ ]*$}}
+# GCN-NEXT: $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+# GCN-NEXT: S_SETPC_B64_return
+---
+name:            swap_phys_liveout
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: swap_phys_liveout_superreg
+# GCN: bb.0:
+# GCN-NEXT: liveins:
+# GCN-NEXT: {{^[ ]*$}}
+# GCN-NEXT: $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+# GCN-NEXT: S_SETPC_B64_return
+---
+name:            swap_phys_liveout_superreg
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: swap_phys_overlap_x
+# GCN: bb.0:
+# GCN-NEXT: liveins:
+# GCN-NEXT: {{^[ ]*$}}
+# GCN-NEXT: $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr3_vgpr4 = V_ADD_F64_e64 0, $vgpr0_vgpr1, 0, $vgpr3_vgpr4, 0, 0, implicit $mode, implicit $exec
+# GCN-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+---
+name:            swap_phys_overlap_x
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_vgpr1, $vgpr3_vgpr4
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+    $vgpr3_vgpr4 = V_ADD_F64_e64 0, $vgpr0_vgpr1, 0, $vgpr3_vgpr4, 0, 0, implicit $mode, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+...
+
+# GCN-LABEL: name: swap_phys_clobber_y
+# GCN: bb.0:
+# GCN-NEXT: liveins:
+# GCN-NEXT: {{^[ ]*$}}
+# GCN-NEXT: $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr1_hi16 = V_MOV_B16_t16_e32 0, implicit $exec
+# GCN-NEXT: $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+---
+name:            swap_phys_clobber_y
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 0, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+    S_ENDPGM 0
+...
+
+# GCN-LABEL: name: swap_virt_copy_vgpr_16
+# GCN: %2:vgpr_16 = COPY %0
+# GCN: %0:vgpr_16 = COPY %1
+# GCN: %1:vgpr_16 = COPY %2
+---
+name:            swap_virt_copy_vgpr_16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: vgpr_16 }
+  - { id: 1, class: vgpr_16 }
+  - { id: 2, class: vgpr_16 }
+body:             |
+  bb.0:
+    %0 = IMPLICIT_DEF
+    %1 = IMPLICIT_DEF
+    %2 = COPY %0
+    %0 = COPY %1
+    %1 = COPY %2
+...
+
+# GCN-LABEL: name: swap_exact_max_insns_apart
+# GCN: bb.0:
+# GCN-NEXT: $vgpr0_lo16 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr1_hi16 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr2_lo16 = COPY $vgpr0_lo16
+# GCN-NEXT: $vgpr3_hi16 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+# GCN-NEXT: S_ENDPGM 0
+---
+name:            swap_exact_max_insns_apart
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    $vgpr0_lo16 = IMPLICIT_DEF
+    $vgpr1_hi16 = IMPLICIT_DEF
+    $vgpr2_lo16 = COPY $vgpr0_lo16
+    $vgpr3_hi16 = IMPLICIT_DEF
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr0_lo16 = COPY $vgpr1_hi16
+    $vgpr1_hi16 = COPY $vgpr2_lo16
+    S_ENDPGM 0
+...
+
+# GCN-LABEL: name: swap_too_far
+# GCN: bb.0:
+# GCN-NEXT: $vgpr0_lo16 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr1_hi16 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr2_lo16 = COPY $vgpr0_lo16
+# GCN-NEXT: $vgpr3_hi16 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr4_lo16 = COPY $vgpr3_hi16
+# GCN-NEXT: $vgpr3_hi16 = COPY $vgpr4_lo16
+# GCN-NEXT: $vgpr0_lo16 = COPY $vgpr1_hi16
+# GCN-NEXT: $vgpr1_hi16 = COPY $vgpr2_lo16
+# GCN-NEXT: S_ENDPGM 0
+---
+name:            swap_too_far
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    $vgpr0_lo16 = IMPLICIT_DEF
+    $vgpr1_hi16 = IMPLICIT_DEF
+    $vgpr2_lo16 = COPY $vgpr0_lo16
+    $vgpr3_hi16 = IMPLICIT_DEF
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr4_lo16 = COPY $vgpr3_hi16
+    $vgpr3_hi16 = COPY $vgpr4_lo16
+    $vgpr0_lo16 = COPY $vgpr1_hi16
+    $vgpr1_hi16 = COPY $vgpr2_lo16
+    S_ENDPGM 0
+...
+
+# GCN-LABEL: name: swap_liveness_error_mov
+# GCN:      $vgpr6_lo16 = V_MOV_B16_t16_e32 $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr1_hi16, $vgpr5_hi16 = V_SWAP_B16 $vgpr5_hi16, $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr5_vgpr6 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr6_lo16 = V_MOV_B16_t16_e32 $vgpr7_hi16, implicit $exec, implicit $vgpr6_vgpr7
+# GCN-NEXT: $vgpr5_hi16 = V_MOV_B16_t16_e32 $vgpr6_lo16, implicit $exec
+---
+name: swap_liveness_error_mov
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr5_hi16, $vgpr1_vgpr2
+    $vgpr6_lo16 = V_MOV_B16_t16_e32 $vgpr1_hi16, implicit $exec, implicit killed $vgpr1_vgpr2
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr5_hi16, implicit $exec
+    $vgpr5_hi16 = V_MOV_B16_t16_e32 $vgpr6_lo16, implicit $exec, implicit-def $vgpr5_vgpr6, implicit $vgpr6_vgpr7
+    $vgpr6_lo16 = V_MOV_B16_t16_e32 $vgpr7_hi16, implicit $exec, implicit $vgpr6_vgpr7
+    $vgpr5_hi16 = V_MOV_B16_t16_e32 $vgpr6_lo16, implicit $exec
+    S_ENDPGM 0
+...
+
+# GCN-LABEL: name: swap_liveness_error_copy
+# GCN:      $vgpr6_lo16 = COPY $vgpr1_hi16
+# GCN-NEXT: $vgpr1_hi16, $vgpr5_hi16 = V_SWAP_B16 $vgpr5_hi16, $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr5_vgpr6 = IMPLICIT_DEF
+# GCN-NEXT: $vgpr6_lo16 = COPY $vgpr7, implicit $vgpr6_vgpr7
+# GCN-NEXT: $vgpr5_hi16 = COPY $vgpr6_lo16
+---
+name: swap_liveness_error_copy
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr5_hi16, $vgpr1_vgpr2
+    $vgpr6_lo16 = COPY $vgpr1_hi16, implicit killed $vgpr1_vgpr2
+    $vgpr1_hi16 = COPY killed $vgpr5_hi16
+    $vgpr5_hi16 = COPY $vgpr6_lo16, implicit-def $vgpr5_vgpr6, implicit $vgpr6_vgpr7
+    $vgpr6_lo16 = COPY $vgpr7, implicit $vgpr6_vgpr7
+    $vgpr5_hi16 = COPY $vgpr6_lo16
+    S_ENDPGM 0
+...
+
+# GCN-LABEL: name: swap_killed_t_early
+# GCN:      $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec, implicit killed $vgpr2_lo16
+# GCN-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec
+# GCN-NEXT: $vgpr1_hi16 = V_MOV_B16_t16_e32 undef $vgpr2_lo16, implicit $exec
+---
+name:            swap_killed_t_early
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $vgpr4_lo16, $vgpr6_lo16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec, implicit killed $vgpr2_lo16
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 undef $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: swap_killed_t_late
+# GCN:      $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec, implicit killed $vgpr2_lo16
+# GCN-NEXT: $vgpr1_hi16 = V_MOV_B16_t16_e32 undef $vgpr2_lo16, implicit $exec
+---
+name:            swap_killed_t_late
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $vgpr4_lo16, $vgpr6_lo16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec, implicit killed $vgpr2_lo16
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 undef $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: swap_killed_x
+# GCN:      $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+# GCN-NEXT: $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec, implicit killed $vgpr0_lo16
+# GCN-NEXT: $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+---
+name:            swap_killed_x
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $vgpr4_lo16, $vgpr6_lo16, $sgpr30_sgpr31
+    $vgpr2_lo16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr4_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 killed $vgpr1_hi16, implicit $exec
+    $vgpr5_hi16 = V_MOV_B16_t16_e32 killed $vgpr6_lo16, implicit $exec, implicit killed $vgpr0_lo16
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr2_lo16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: name: implicit_ops_mov_x_swap_b16
+# GCN: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec, implicit $vgpr2_lo16, implicit killed $vgpr1_vgpr2
+---
+name:            implicit_ops_mov_x_swap_b16
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $sgpr30_sgpr31
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 $vgpr1_hi16, implicit $exec, implicit $vgpr2_lo16, implicit killed $vgpr1_vgpr2
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr3_hi16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: implicit_ops_mov_t_swap_b16
+# GCN:      $vgpr3_hi16 = V_MOV_B16_t16_e32 $vgpr0_lo16, implicit $exec, implicit $vgpr2_lo16, implicit killed $vgpr1_vgpr2, implicit-def $vgpr1_hi16
+# GCN-NEXT: $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+
+---
+name:            implicit_ops_mov_t_swap_b16
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $sgpr30_sgpr31
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec, implicit $vgpr2_lo16, implicit killed $vgpr1_vgpr2, implicit-def $vgpr1_hi16
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr3_hi16, implicit $exec
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...
+
+# GCN-LABEL: implicit_ops_mov_y_swap_b16
+# GCN:      $vgpr0_lo16, $vgpr1_hi16 = V_SWAP_B16 $vgpr1_hi16, $vgpr0_lo16, implicit $exec
+# GCN-NEXT: $vgpr0_vgpr1 = IMPLICIT_DEF
+---
+name:            implicit_ops_mov_y_swap_b16
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_lo16, $vgpr1_hi16, $vgpr2_lo16, $sgpr30_sgpr31
+    $vgpr3_hi16 = V_MOV_B16_t16_e32 killed $vgpr0_lo16, implicit $exec
+    $vgpr0_lo16 = V_MOV_B16_t16_e32 $vgpr1_hi16, implicit $exec
+    $vgpr1_hi16 = V_MOV_B16_t16_e32 killed $vgpr3_hi16, implicit $exec, implicit $vgpr2_lo16, implicit-def $vgpr0_vgpr1, implicit killed $vgpr3_hi16
+    S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0_lo16, implicit $vgpr1_hi16
+...

>From ac93cc3c9cf5a642f6f05444f3444ddb846972c3 Mon Sep 17 00:00:00 2001
From: guochen2 <guochen2 at amd.com>
Date: Wed, 24 Jul 2024 16:29:39 -0400
Subject: [PATCH 3/3] update lit test

---
 llvm/test/CodeGen/AMDGPU/v_swap_b16.ll  | 13 +++++++------
 llvm/test/CodeGen/AMDGPU/v_swap_b16.mir |  2 +-
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll b/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll
index fa8c39f367694..4b8788d5c0939 100644
--- a/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll
+++ b/llvm/test/CodeGen/AMDGPU/v_swap_b16.ll
@@ -1,25 +1,26 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -march=amdgcn -mcpu=gfx1100 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX11 %s
+; RUN: llc -march=amdgcn -mcpu=gfx1100 -mattr=+real-true16 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX11 %s
 
 define half @swap(half %a, half %b, i32 %i) {
 ; GFX11-LABEL: swap:
 ; GFX11:       ; %bb.0: ; %entry
 ; GFX11-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-NEXT:    s_waitcnt_vscnt null, 0x0
+; GFX11-NEXT:    v_mov_b16_e32 v0.h, v0.l
+; GFX11-NEXT:    v_mov_b16_e32 v0.l, v1.l
 ; GFX11-NEXT:    s_mov_b32 s0, 0
 ; GFX11-NEXT:  .LBB0_1: ; %loop
 ; GFX11-NEXT:    ; =>This Inner Loop Header: Depth=1
 ; GFX11-NEXT:    v_add_nc_u32_e32 v2, -1, v2
-; GFX11-NEXT:    v_mov_b16_e32 v0.h, v1.l
-; GFX11-NEXT:    v_swap_b16 v1.l, v0.l
-; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_3) | instskip(SKIP_1) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_3)
+; GFX11-NEXT:    v_mov_b16_e32 v1.l, v0.l
+; GFX11-NEXT:    v_swap_b16 v0.l, v0.h
 ; GFX11-NEXT:    v_cmp_eq_u32_e32 vcc_lo, 0, v2
 ; GFX11-NEXT:    s_or_b32 s0, vcc_lo, s0
+; GFX11-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX11-NEXT:    s_and_not1_b32 exec_lo, exec_lo, s0
 ; GFX11-NEXT:    s_cbranch_execnz .LBB0_1
 ; GFX11-NEXT:  ; %bb.2: ; %ret
 ; GFX11-NEXT:    s_or_b32 exec_lo, exec_lo, s0
-; GFX11-NEXT:    v_mov_b16_e32 v0.l, v1.l
 ; GFX11-NEXT:    s_setpc_b64 s[30:31]
 entry:
   br label %loop
diff --git a/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir b/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir
index 28d4b39ad7b04..8386546e7f57d 100644
--- a/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir
+++ b/llvm/test/CodeGen/AMDGPU/v_swap_b16.mir
@@ -1,4 +1,4 @@
-# RUN: llc -simplify-mir -march=amdgcn -mcpu=gfx1100 -run-pass=si-shrink-instructions -verify-machineinstrs %s -o - | FileCheck -check-prefix=GCN %s
+# RUN: llc -simplify-mir -march=amdgcn -mcpu=gfx1100 -mattr=+real-true16 -run-pass=si-shrink-instructions -verify-machineinstrs %s -o - | FileCheck -check-prefix=GCN %s
 
 # GCN-LABEL: name: swap_phys_condensed
 # GCN: bb.0:



More information about the llvm-commits mailing list