[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
This commit is contained in:
parent
38d6202a42
commit
96a661de4b
|
@ -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",
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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>)
|
||||
...
|
||||
|
|
|
@ -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
|
||||
|
||||
...
|
||||
|
||||
|
|
|
@ -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
|
||||
...
|
Loading…
Reference in New Issue