AMDGPU/GlobalISel: Select G_TRUNC

llvm-svn: 364215
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 590fd25..45bf1f6 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -555,6 +555,76 @@
   return Ret;
 }
 
+static int sizeToSubRegIndex(unsigned Size) {
+  switch (Size) {
+  case 32:
+    return AMDGPU::sub0;
+  case 64:
+    return AMDGPU::sub0_sub1;
+  case 96:
+    return AMDGPU::sub0_sub1_sub2;
+  case 128:
+    return AMDGPU::sub0_sub1_sub2_sub3;
+  case 256:
+    return AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7;
+  default:
+    if (Size < 32)
+      return AMDGPU::sub0;
+    if (Size > 256)
+      return -1;
+    return sizeToSubRegIndex(PowerOf2Ceil(Size));
+  }
+}
+
+bool AMDGPUInstructionSelector::selectG_TRUNC(MachineInstr &I) const {
+  MachineBasicBlock *BB = I.getParent();
+  MachineFunction *MF = BB->getParent();
+  MachineRegisterInfo &MRI = MF->getRegInfo();
+
+  unsigned DstReg = I.getOperand(0).getReg();
+  unsigned SrcReg = I.getOperand(1).getReg();
+  const LLT DstTy = MRI.getType(DstReg);
+  const LLT SrcTy = MRI.getType(SrcReg);
+  if (!DstTy.isScalar())
+    return false;
+
+  const RegisterBank *DstRB = RBI.getRegBank(DstReg, MRI, TRI);
+  const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, MRI, TRI);
+  if (SrcRB != DstRB)
+    return false;
+
+  unsigned DstSize = DstTy.getSizeInBits();
+  unsigned SrcSize = SrcTy.getSizeInBits();
+
+  const TargetRegisterClass *SrcRC
+    = TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB, MRI);
+  const TargetRegisterClass *DstRC
+    = TRI.getRegClassForSizeOnBank(DstSize, *DstRB, MRI);
+
+  if (SrcSize > 32) {
+    int SubRegIdx = sizeToSubRegIndex(DstSize);
+    if (SubRegIdx == -1)
+      return false;
+
+    // Deal with weird cases where the class only partially supports the subreg
+    // index.
+    SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
+    if (!SrcRC)
+      return false;
+
+    I.getOperand(1).setSubReg(SubRegIdx);
+  }
+
+  if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
+      !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
+    LLVM_DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
+    return false;
+  }
+
+  I.setDesc(TII.get(TargetOpcode::COPY));
+  return true;
+}
+
 bool AMDGPUInstructionSelector::selectG_CONSTANT(MachineInstr &I) const {
   MachineBasicBlock *BB = I.getParent();
   MachineFunction *MF = BB->getParent();
@@ -770,6 +840,8 @@
     return selectG_SELECT(I);
   case TargetOpcode::G_STORE:
     return selectG_STORE(I);
+  case TargetOpcode::G_TRUNC:
+    return selectG_TRUNC(I);
   }
   return false;
 }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
index 35f528f..8cee015 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
@@ -63,6 +63,7 @@
 
   MachineOperand getSubOperand64(MachineOperand &MO, unsigned SubIdx) const;
   bool selectCOPY(MachineInstr &I) const;
+  bool selectG_TRUNC(MachineInstr &I) const;
   bool selectG_CONSTANT(MachineInstr &I) const;
   bool selectG_ADD(MachineInstr &I) const;
   bool selectG_EXTRACT(MachineInstr &I) const;
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index fe675b5..6e7d47b 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -1679,17 +1679,12 @@
 }
 
 const TargetRegisterClass *
-SIRegisterInfo::getConstrainedRegClassForOperand(const MachineOperand &MO,
+SIRegisterInfo::getRegClassForSizeOnBank(unsigned Size,
+                                         const RegisterBank &RB,
                                          const MachineRegisterInfo &MRI) const {
-  unsigned Size = getRegSizeInBits(MO.getReg(), MRI);
-  const RegisterBank *RB = MRI.getRegBankOrNull(MO.getReg());
-  if (!RB)
-    return nullptr;
-
-  Size = PowerOf2Ceil(Size);
   switch (Size) {
   case 1: {
-    switch (RB->getID()) {
+    switch (RB.getID()) {
     case AMDGPU::VGPRRegBankID:
       return &AMDGPU::VGPR_32RegClass;
     case AMDGPU::VCCRegBankID:
@@ -1706,30 +1701,41 @@
     }
   }
   case 32:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VGPR_32RegClass :
-                                                  &AMDGPU::SReg_32_XM0RegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VGPR_32RegClass :
+                                                 &AMDGPU::SReg_32_XM0RegClass;
   case 64:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_64RegClass :
-                                                   &AMDGPU::SReg_64_XEXECRegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_64RegClass :
+                                                  &AMDGPU::SReg_64_XEXECRegClass;
   case 96:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_96RegClass :
-                                                  &AMDGPU::SReg_96RegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_96RegClass :
+                                                 &AMDGPU::SReg_96RegClass;
   case 128:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_128RegClass :
-                                                  &AMDGPU::SReg_128RegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_128RegClass :
+                                                 &AMDGPU::SReg_128RegClass;
   case 160:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_160RegClass :
-                                                  &AMDGPU::SReg_160RegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_160RegClass :
+                                                 &AMDGPU::SReg_160RegClass;
   case 256:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_256RegClass :
-                                                  &AMDGPU::SReg_256RegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_256RegClass :
+                                                 &AMDGPU::SReg_256RegClass;
   case 512:
-    return RB->getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_512RegClass :
-                                                  &AMDGPU::SReg_512RegClass;
+    return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VReg_512RegClass :
+                                                 &AMDGPU::SReg_512RegClass;
   default:
-    break;
+    if (Size < 32)
+      return RB.getID() == AMDGPU::VGPRRegBankID ? &AMDGPU::VGPR_32RegClass :
+                                                   &AMDGPU::SReg_32_XM0RegClass;
+    assert(Size < 512 && "unimplemented");
+    return getRegClassForSizeOnBank(PowerOf2Ceil(Size), RB, MRI);
   }
-  llvm_unreachable("not implemented");
+}
+
+const TargetRegisterClass *
+SIRegisterInfo::getConstrainedRegClassForOperand(const MachineOperand &MO,
+                                         const MachineRegisterInfo &MRI) const {
+  if (const RegisterBank *RB = MRI.getRegBankOrNull(MO.getReg()))
+    return getRegClassForTypeOnBank(MRI.getType(MO.getReg()), *RB, MRI);
+  return nullptr;
 }
 
 unsigned SIRegisterInfo::getVCC() const {
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 8a42b09..4f11403 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -229,6 +229,18 @@
   unsigned getReturnAddressReg(const MachineFunction &MF) const;
 
   const TargetRegisterClass *
+  getRegClassForSizeOnBank(unsigned Size,
+                           const RegisterBank &Bank,
+                           const MachineRegisterInfo &MRI) const;
+
+  const TargetRegisterClass *
+  getRegClassForTypeOnBank(LLT Ty,
+                           const RegisterBank &Bank,
+                           const MachineRegisterInfo &MRI) const {
+    return getRegClassForSizeOnBank(Ty.getSizeInBits(), Bank, MRI);
+  }
+
+  const TargetRegisterClass *
   getConstrainedRegClassForOperand(const MachineOperand &MO,
                                  const MachineRegisterInfo &MRI) const override;
 
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-trunc.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-trunc.mir
new file mode 100644
index 0000000..390f5d2
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-trunc.mir
@@ -0,0 +1,373 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=amdgcn -run-pass=instruction-select -verify-machineinstrs  %s -o - | FileCheck %s -check-prefixes=GCN
+
+---
+
+name: trunc_sgpr_s32_to_s1
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0
+    ; GCN-LABEL: name: trunc_sgpr_s32_to_s1
+    ; GCN: [[COPY:%[0-9]+]]:sreg_32_xm0 = COPY $sgpr0
+    ; GCN: S_ENDPGM 0, implicit [[COPY]]
+    %0:sgpr(s32) =COPY $sgpr0
+    %1:sgpr(s1) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s32_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0
+    ; GCN-LABEL: name: trunc_sgpr_s32_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:sreg_32_xm0 = COPY $sgpr0
+    ; GCN: S_ENDPGM 0, implicit [[COPY]]
+    %0:sgpr(s32) =COPY $sgpr0
+    %1:sgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s64_to_s32
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1
+    ; GCN-LABEL: name: trunc_sgpr_s64_to_s32
+    ; GCN: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr0_sgpr1
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_32_xm0 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s64) = COPY $sgpr0_sgpr1
+    %1:sgpr(s32) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s64_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1
+    ; GCN-LABEL: name: trunc_sgpr_s64_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr0_sgpr1
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_32_xm0 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s64) = COPY $sgpr0_sgpr1
+    %1:sgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s64_to_s1
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1
+    ; GCN-LABEL: name: trunc_sgpr_s64_to_s1
+    ; GCN: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr0_sgpr1
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_32_xm0 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s64) = COPY $sgpr0_sgpr1
+    %1:sgpr(s1) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s96_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2
+    ; GCN-LABEL: name: trunc_sgpr_s96_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:sreg_96 = COPY $sgpr0_sgpr1_sgpr2
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_32_xm0 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s96) = COPY $sgpr0_sgpr1_sgpr2
+    %1:sgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s96_to_s64
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2
+    ; GCN-LABEL: name: trunc_sgpr_s96_to_s64
+    ; GCN: [[COPY:%[0-9]+]]:sgpr_96_with_sub0_sub1 = COPY $sgpr0_sgpr1_sgpr2
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_64_xexec = COPY [[COPY]].sub0_sub1
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s96) = COPY $sgpr0_sgpr1_sgpr2
+    %1:sgpr(s64) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s128_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GCN-LABEL: name: trunc_sgpr_s128_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:sreg_128 = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_32_xm0 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s128) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    %1:sgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s128_to_s96
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GCN-LABEL: name: trunc_sgpr_s128_to_s96
+    ; GCN: [[COPY:%[0-9]+]]:sgpr_128_with_sub0_sub1_sub2 = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_96 = COPY [[COPY]].sub0_sub1_sub2
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s128) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    %1:sgpr(s96) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s256_to_s128
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7
+    ; GCN-LABEL: name: trunc_sgpr_s256_to_s128
+    ; GCN: [[COPY:%[0-9]+]]:sreg_256 = COPY $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_128 = COPY [[COPY]].sub0_sub1_sub2_sub3
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s256) = COPY $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7
+    %1:sgpr(s128) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_sgpr_s512_to_s256
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7_sgpr8_sgpr9_sgpr10_sgpr11_sgpr12_sgpr13_sgpr14_sgpr15
+    ; GCN-LABEL: name: trunc_sgpr_s512_to_s256
+    ; GCN: [[COPY:%[0-9]+]]:sreg_512 = COPY $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7_sgpr8_sgpr9_sgpr10_sgpr11_sgpr12_sgpr13_sgpr14_sgpr15
+    ; GCN: [[COPY1:%[0-9]+]]:sreg_256 = COPY [[COPY]].sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:sgpr(s512) = COPY $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7_sgpr8_sgpr9_sgpr10_sgpr11_sgpr12_sgpr13_sgpr14_sgpr15
+    %1:sgpr(s256) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s32_to_s1
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0
+    ; GCN-LABEL: name: trunc_vgpr_s32_to_s1
+    ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0
+    ; GCN: S_ENDPGM 0, implicit [[COPY]]
+    %0:vgpr(s32) =COPY $vgpr0
+    %1:vgpr(s1) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s32_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0
+    ; GCN-LABEL: name: trunc_vgpr_s32_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0
+    ; GCN: S_ENDPGM 0, implicit [[COPY]]
+    %0:vgpr(s32) =COPY $vgpr0
+    %1:vgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s64_to_s32
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1
+    ; GCN-LABEL: name: trunc_vgpr_s64_to_s32
+    ; GCN: [[COPY:%[0-9]+]]:vreg_64 = COPY $vgpr0_vgpr1
+    ; GCN: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s64) = COPY $vgpr0_vgpr1
+    %1:vgpr(s32) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s64_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1
+    ; GCN-LABEL: name: trunc_vgpr_s64_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:vreg_64 = COPY $vgpr0_vgpr1
+    ; GCN: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s64) = COPY $vgpr0_vgpr1
+    %1:vgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s64_to_s1
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1
+    ; GCN-LABEL: name: trunc_vgpr_s64_to_s1
+    ; GCN: [[COPY:%[0-9]+]]:vreg_64 = COPY $vgpr0_vgpr1
+    ; GCN: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s64) = COPY $vgpr0_vgpr1
+    %1:vgpr(s1) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s96_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1_vgpr2
+    ; GCN-LABEL: name: trunc_vgpr_s96_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:vreg_96 = COPY $vgpr0_vgpr1_vgpr2
+    ; GCN: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s96) = COPY $vgpr0_vgpr1_vgpr2
+    %1:vgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s96_to_s64
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1_vgpr2
+    ; GCN-LABEL: name: trunc_vgpr_s96_to_s64
+    ; GCN: [[COPY:%[0-9]+]]:vreg_96 = COPY $vgpr0_vgpr1_vgpr2
+    ; GCN: [[COPY1:%[0-9]+]]:vreg_64 = COPY [[COPY]].sub0_sub1
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s96) = COPY $vgpr0_vgpr1_vgpr2
+    %1:vgpr(s64) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s128_to_s16
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1_vgpr2_vgpr3
+    ; GCN-LABEL: name: trunc_vgpr_s128_to_s16
+    ; GCN: [[COPY:%[0-9]+]]:vreg_128 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+    ; GCN: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[COPY]].sub0
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s128) = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+    %1:vgpr(s16) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s128_to_s96
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1_vgpr2_vgpr3
+    ; GCN-LABEL: name: trunc_vgpr_s128_to_s96
+    ; GCN: [[COPY:%[0-9]+]]:vreg_128 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+    ; GCN: [[COPY1:%[0-9]+]]:vreg_96 = COPY [[COPY]].sub0_sub1_sub2
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s128) = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+    %1:vgpr(s96) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s256_to_s128
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7
+    ; GCN-LABEL: name: trunc_vgpr_s256_to_s128
+    ; GCN: [[COPY:%[0-9]+]]:vreg_256 = COPY $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7
+    ; GCN: [[COPY1:%[0-9]+]]:vreg_128 = COPY [[COPY]].sub0_sub1_sub2_sub3
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s256) = COPY $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7
+    %1:vgpr(s128) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...
+---
+
+name: trunc_vgpr_s512_to_s256
+legalized:       true
+regBankSelected: true
+
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
+    ; GCN-LABEL: name: trunc_vgpr_s512_to_s256
+    ; GCN: [[COPY:%[0-9]+]]:vreg_512 = COPY $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
+    ; GCN: [[COPY1:%[0-9]+]]:vreg_256 = COPY [[COPY]].sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7
+    ; GCN: S_ENDPGM 0, implicit [[COPY1]]
+    %0:vgpr(s512) = COPY $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
+    %1:vgpr(s256) = G_TRUNC %0
+    S_ENDPGM 0, implicit %1
+...