[llvm] 96a661d - [GlobalISel] Better verification of G_UNMERGE_VALUES

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 17 00:20:07 PST 2022


Author: Jay Foad
Date: 2022-11-17T08:19:57Z
New Revision: 96a661de4b103e05993bec2783b90d300539a05e

URL: https://github.com/llvm/llvm-project/commit/96a661de4b103e05993bec2783b90d300539a05e
DIFF: https://github.com/llvm/llvm-project/commit/96a661de4b103e05993bec2783b90d300539a05e.diff

LOG: [GlobalISel] Better verification of G_UNMERGE_VALUES

Verify three cases of G_UNMERGE_VALUES separately:

1. Splitting a vector into subvectors (the converse of
   G_CONCAT_VECTORS).
2. Splitting a vector into its elements (the converse of
   G_BUILD_VECTOR).
3. Splitting a scalar into smaller scalars (the converse of
   G_MERGE_VALUES).

Previously #1 allowed strange combinations like this:
  %1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(<2 x s32>)
This has been tightened up to check that the source and destination
element types match, and some MIR test cases updated accordingly.

Differential Revision: https://reviews.llvm.org/D111132

Added: 
    llvm/test/MachineVerifier/test_g_unmerge_values.mir

Modified: 
    llvm/lib/CodeGen/MachineVerifier.cpp
    llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir
    llvm/test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-unmerge-values.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 63c6a15bbfabd..870a7691e7606 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1311,17 +1311,38 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
     break;
   }
   case TargetOpcode::G_UNMERGE_VALUES: {
+    unsigned NumDsts = MI->getNumOperands() - 1;
     LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
-    LLT SrcTy = MRI->getType(MI->getOperand(MI->getNumOperands()-1).getReg());
-    // For now G_UNMERGE can split vectors.
-    for (unsigned i = 0; i < MI->getNumOperands()-1; ++i) {
-      if (MRI->getType(MI->getOperand(i).getReg()) != DstTy)
+    for (unsigned i = 1; i < NumDsts; ++i) {
+      if (MRI->getType(MI->getOperand(i).getReg()) != DstTy) {
         report("G_UNMERGE_VALUES destination types do not match", MI);
+        break;
+      }
     }
-    if (SrcTy.getSizeInBits() !=
-        (DstTy.getSizeInBits() * (MI->getNumOperands() - 1))) {
-      report("G_UNMERGE_VALUES source operand does not cover dest operands",
-             MI);
+
+    LLT SrcTy = MRI->getType(MI->getOperand(NumDsts).getReg());
+    if (DstTy.isVector()) {
+      // This case is the converse of G_CONCAT_VECTORS.
+      if (!SrcTy.isVector() || SrcTy.getScalarType() != DstTy.getScalarType() ||
+          SrcTy.getNumElements() != NumDsts * DstTy.getNumElements())
+        report("G_UNMERGE_VALUES source operand does not match vector "
+               "destination operands",
+               MI);
+    } else if (SrcTy.isVector()) {
+      // This case is the converse of G_BUILD_VECTOR, but relaxed to allow
+      // mismatched types as long as the total size matches:
+      //   %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<4 x s32>)
+      if (SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits())
+        report("G_UNMERGE_VALUES vector source operand does not match scalar "
+               "destination operands",
+               MI);
+    } else {
+      // This case is the converse of G_MERGE_VALUES.
+      if (SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits()) {
+        report("G_UNMERGE_VALUES scalar source operand does not match scalar "
+               "destination operands",
+               MI);
+      }
     }
     break;
   }

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir
index 53c75b4d84d95..01a4f65a9c6c1 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir
@@ -328,13 +328,13 @@ name:            test_combine_unmerge_dead_to_trunc_vec_in_n_out
 body:             |
   bb.1:
     ; CHECK-LABEL: name: test_combine_unmerge_dead_to_trunc_vec_in_n_out
-    ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $x0
-    ; CHECK: [[BITCAST:%[0-9]+]]:_(s64) = G_BITCAST [[COPY]](<2 x s32>)
+    ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $x0
+    ; CHECK: [[BITCAST:%[0-9]+]]:_(s64) = G_BITCAST [[COPY]](<4 x s16>)
     ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[BITCAST]](s64)
     ; CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[TRUNC]](s32)
     ; CHECK: $w0 = COPY [[BITCAST1]](<2 x s16>)
-    %0:_(<2 x s32>) = COPY $x0
-    %1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(<2 x s32>)
+    %0:_(<4 x s16>) = COPY $x0
+    %1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(<4 x s16>)
     $w0 = COPY %1(<2 x s16>)
 ...
 
@@ -354,22 +354,6 @@ body:             |
     $h0 = COPY %1(s16)
 ...
 
-# Transform unmerge into trunc when only the first definition is live, even
-# if the output type are vector.
----
-name:            test_combine_unmerge_dead_to_trunc_vec_out
-body:             |
-  bb.1:
-    ; CHECK-LABEL: name: test_combine_unmerge_dead_to_trunc_vec_out
-    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
-    ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
-    ; CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[TRUNC]](s32)
-    ; CHECK: $w0 = COPY [[BITCAST]](<2 x s16>)
-    %0:_(s64) = COPY $x0
-    %1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(s64)
-    $w0 = COPY %1(<2 x s16>)
-...
-
 # Transform unmerge(zext) into zext.
 # In that test, the source of the zext is same size as the first definition
 # of the unmerge. Therefore a we can just reuse the input of the zext for
@@ -456,23 +440,3 @@ body:             |
     $w0 = COPY %1(s32)
     $w1 = COPY %2(s32)
 ...
-
-# Check that we don't apply the unmerge(zext) to zext transformation
-# when the destination type is a vector type.
-# We could actually handle this case but we would need to insert a cast.
----
-name:            test_dont_combine_unmerge_zext_to_zext_dst_vector
-body:             |
-  bb.1:
-    ; CHECK-LABEL: name: test_dont_combine_unmerge_zext_to_zext_dst_vector
-    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
-    ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s32)
-    ; CHECK: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[ZEXT]](s64)
-    ; CHECK: $w0 = COPY [[UV]](<2 x s16>)
-    ; CHECK: $w1 = COPY [[UV1]](<2 x s16>)
-    %0:_(s32) = COPY $w0
-    %3:_(s64) = G_ZEXT %0(s32)
-    %1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %3(s64)
-    $w0 = COPY %1(<2 x s16>)
-    $w1 = COPY %2(<2 x s16>)
-...

diff  --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-unmerge-values.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-unmerge-values.mir
index 95e5647d9215d..4c3463eb4909d 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-unmerge-values.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-unmerge-values.mir
@@ -215,11 +215,9 @@ body:             |
     ; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[ANYEXT1]](s16)
     ; CHECK-NEXT: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[ANYEXT]](s16)
     ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[ANYEXT1]](s16)
-    ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT]](s32)
-    ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT1]](s32)
-    ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT2]](s32)
-    ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT3]](s32)
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[BITCAST]](<2 x s16>), implicit [[BITCAST1]](<2 x s16>), implicit [[BITCAST2]](<2 x s16>), implicit [[BITCAST3]](<2 x s16>)
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ZEXT]](s32), [[ZEXT1]](s32)
+    ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ZEXT2]](s32), [[ZEXT3]](s32)
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[BUILD_VECTOR]](<2 x s32>), implicit [[BUILD_VECTOR1]](<2 x s32>)
     %0:_(<2 x s32>) = COPY $vgpr0_vgpr1
     %1:_(<2 x s32>) = COPY $vgpr0_vgpr1
     %2:_(s32), %3:_(s32) = G_UNMERGE_VALUES %0(<2 x s32>)
@@ -230,8 +228,8 @@ body:             |
     %9:_(s16) = G_ANYEXT %7
     %10:_(<4 x s16>) = G_BUILD_VECTOR %8, %9, %8, %9
     %11:_(<4 x s32>) = G_ZEXT %10
-    %12:_(<2 x s16>), %13:_(<2 x s16>), %14:_(<2 x s16>), %15:_(<2 x s16>) = G_UNMERGE_VALUES %11
-    S_ENDPGM 0, implicit %12, implicit %13, implicit %14, implicit %15
+    %12:_(<2 x s32>), %13:_(<2 x s32>) = G_UNMERGE_VALUES %11
+    S_ENDPGM 0, implicit %12, implicit %13
 
 ...
 

diff  --git a/llvm/test/MachineVerifier/test_g_unmerge_values.mir b/llvm/test/MachineVerifier/test_g_unmerge_values.mir
new file mode 100644
index 0000000000000..bad11fd2489bb
--- /dev/null
+++ b/llvm/test/MachineVerifier/test_g_unmerge_values.mir
@@ -0,0 +1,33 @@
+# RUN: not --crash llc -o - -march=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+---
+name: g_unmerge_values
+tracksRegLiveness: true
+body: |
+  bb.0:
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES destination types do not match
+    %0:_(s64) = IMPLICIT_DEF
+    %1:_(s32), %2:_(s16) = G_UNMERGE_VALUES %0
+
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES source operand does not match vector destination operands
+    %3:_(<4 x s32>) = IMPLICIT_DEF
+    %4:_(<3 x s32>), %5:_(<3 x s32>) = G_UNMERGE_VALUES %3
+
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES source operand does not match vector destination operands
+    %6:_(<2 x s16>), %7:_(<2 x s16>) = G_UNMERGE_VALUES %3
+
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES vector source operand does not match scalar destination operands
+    %8:_(<2 x s32>) = IMPLICIT_DEF
+    %9:_(s32), %10:_(s32), %11:_(s32) = G_UNMERGE_VALUES %8
+
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES vector source operand does not match scalar destination operands
+    %12:_(s16), %13:_(s16) = G_UNMERGE_VALUES %8
+
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES scalar source operand does not match scalar destination operands
+    %14:_(s64) = IMPLICIT_DEF
+    %15:_(s16), %16:_(s16) = G_UNMERGE_VALUES %14
+
+    ; CHECK: Bad machine code: G_UNMERGE_VALUES scalar source operand does not match scalar destination operands
+    %17:_(s32), %18:_(s32), %19:_(s32) = G_UNMERGE_VALUES %14
+...


        


More information about the llvm-commits mailing list