Skip to content

Commit 96a661d

Browse files
committed
[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
1 parent 38d6202 commit 96a661d

File tree

4 files changed

+71
-55
lines changed

4 files changed

+71
-55
lines changed

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,17 +1311,38 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
13111311
break;
13121312
}
13131313
case TargetOpcode::G_UNMERGE_VALUES: {
1314+
unsigned NumDsts = MI->getNumOperands() - 1;
13141315
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
1315-
LLT SrcTy = MRI->getType(MI->getOperand(MI->getNumOperands()-1).getReg());
1316-
// For now G_UNMERGE can split vectors.
1317-
for (unsigned i = 0; i < MI->getNumOperands()-1; ++i) {
1318-
if (MRI->getType(MI->getOperand(i).getReg()) != DstTy)
1316+
for (unsigned i = 1; i < NumDsts; ++i) {
1317+
if (MRI->getType(MI->getOperand(i).getReg()) != DstTy) {
13191318
report("G_UNMERGE_VALUES destination types do not match", MI);
1319+
break;
1320+
}
13201321
}
1321-
if (SrcTy.getSizeInBits() !=
1322-
(DstTy.getSizeInBits() * (MI->getNumOperands() - 1))) {
1323-
report("G_UNMERGE_VALUES source operand does not cover dest operands",
1324-
MI);
1322+
1323+
LLT SrcTy = MRI->getType(MI->getOperand(NumDsts).getReg());
1324+
if (DstTy.isVector()) {
1325+
// This case is the converse of G_CONCAT_VECTORS.
1326+
if (!SrcTy.isVector() || SrcTy.getScalarType() != DstTy.getScalarType() ||
1327+
SrcTy.getNumElements() != NumDsts * DstTy.getNumElements())
1328+
report("G_UNMERGE_VALUES source operand does not match vector "
1329+
"destination operands",
1330+
MI);
1331+
} else if (SrcTy.isVector()) {
1332+
// This case is the converse of G_BUILD_VECTOR, but relaxed to allow
1333+
// mismatched types as long as the total size matches:
1334+
// %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<4 x s32>)
1335+
if (SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits())
1336+
report("G_UNMERGE_VALUES vector source operand does not match scalar "
1337+
"destination operands",
1338+
MI);
1339+
} else {
1340+
// This case is the converse of G_MERGE_VALUES.
1341+
if (SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits()) {
1342+
report("G_UNMERGE_VALUES scalar source operand does not match scalar "
1343+
"destination operands",
1344+
MI);
1345+
}
13251346
}
13261347
break;
13271348
}

llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,13 @@ name: test_combine_unmerge_dead_to_trunc_vec_in_n_out
328328
body: |
329329
bb.1:
330330
; CHECK-LABEL: name: test_combine_unmerge_dead_to_trunc_vec_in_n_out
331-
; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $x0
332-
; CHECK: [[BITCAST:%[0-9]+]]:_(s64) = G_BITCAST [[COPY]](<2 x s32>)
331+
; CHECK: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $x0
332+
; CHECK: [[BITCAST:%[0-9]+]]:_(s64) = G_BITCAST [[COPY]](<4 x s16>)
333333
; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[BITCAST]](s64)
334334
; CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[TRUNC]](s32)
335335
; CHECK: $w0 = COPY [[BITCAST1]](<2 x s16>)
336-
%0:_(<2 x s32>) = COPY $x0
337-
%1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(<2 x s32>)
336+
%0:_(<4 x s16>) = COPY $x0
337+
%1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(<4 x s16>)
338338
$w0 = COPY %1(<2 x s16>)
339339
...
340340

@@ -354,22 +354,6 @@ body: |
354354
$h0 = COPY %1(s16)
355355
...
356356

357-
# Transform unmerge into trunc when only the first definition is live, even
358-
# if the output type are vector.
359-
---
360-
name: test_combine_unmerge_dead_to_trunc_vec_out
361-
body: |
362-
bb.1:
363-
; CHECK-LABEL: name: test_combine_unmerge_dead_to_trunc_vec_out
364-
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
365-
; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
366-
; CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[TRUNC]](s32)
367-
; CHECK: $w0 = COPY [[BITCAST]](<2 x s16>)
368-
%0:_(s64) = COPY $x0
369-
%1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %0(s64)
370-
$w0 = COPY %1(<2 x s16>)
371-
...
372-
373357
# Transform unmerge(zext) into zext.
374358
# In that test, the source of the zext is same size as the first definition
375359
# of the unmerge. Therefore a we can just reuse the input of the zext for
@@ -456,23 +440,3 @@ body: |
456440
$w0 = COPY %1(s32)
457441
$w1 = COPY %2(s32)
458442
...
459-
460-
# Check that we don't apply the unmerge(zext) to zext transformation
461-
# when the destination type is a vector type.
462-
# We could actually handle this case but we would need to insert a cast.
463-
---
464-
name: test_dont_combine_unmerge_zext_to_zext_dst_vector
465-
body: |
466-
bb.1:
467-
; CHECK-LABEL: name: test_dont_combine_unmerge_zext_to_zext_dst_vector
468-
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
469-
; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s32)
470-
; CHECK: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[ZEXT]](s64)
471-
; CHECK: $w0 = COPY [[UV]](<2 x s16>)
472-
; CHECK: $w1 = COPY [[UV1]](<2 x s16>)
473-
%0:_(s32) = COPY $w0
474-
%3:_(s64) = G_ZEXT %0(s32)
475-
%1:_(<2 x s16>),%2:_(<2 x s16>) = G_UNMERGE_VALUES %3(s64)
476-
$w0 = COPY %1(<2 x s16>)
477-
$w1 = COPY %2(<2 x s16>)
478-
...

llvm/test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-unmerge-values.mir

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,9 @@ body: |
215215
; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[ANYEXT1]](s16)
216216
; CHECK-NEXT: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[ANYEXT]](s16)
217217
; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[ANYEXT1]](s16)
218-
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT]](s32)
219-
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT1]](s32)
220-
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT2]](s32)
221-
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[ZEXT3]](s32)
222-
; 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>)
218+
; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ZEXT]](s32), [[ZEXT1]](s32)
219+
; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ZEXT2]](s32), [[ZEXT3]](s32)
220+
; CHECK-NEXT: S_ENDPGM 0, implicit [[BUILD_VECTOR]](<2 x s32>), implicit [[BUILD_VECTOR1]](<2 x s32>)
223221
%0:_(<2 x s32>) = COPY $vgpr0_vgpr1
224222
%1:_(<2 x s32>) = COPY $vgpr0_vgpr1
225223
%2:_(s32), %3:_(s32) = G_UNMERGE_VALUES %0(<2 x s32>)
@@ -230,8 +228,8 @@ body: |
230228
%9:_(s16) = G_ANYEXT %7
231229
%10:_(<4 x s16>) = G_BUILD_VECTOR %8, %9, %8, %9
232230
%11:_(<4 x s32>) = G_ZEXT %10
233-
%12:_(<2 x s16>), %13:_(<2 x s16>), %14:_(<2 x s16>), %15:_(<2 x s16>) = G_UNMERGE_VALUES %11
234-
S_ENDPGM 0, implicit %12, implicit %13, implicit %14, implicit %15
231+
%12:_(<2 x s32>), %13:_(<2 x s32>) = G_UNMERGE_VALUES %11
232+
S_ENDPGM 0, implicit %12, implicit %13
235233
236234
...
237235

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# RUN: not --crash llc -o - -march=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
2+
# REQUIRES: aarch64-registered-target
3+
4+
---
5+
name: g_unmerge_values
6+
tracksRegLiveness: true
7+
body: |
8+
bb.0:
9+
; CHECK: Bad machine code: G_UNMERGE_VALUES destination types do not match
10+
%0:_(s64) = IMPLICIT_DEF
11+
%1:_(s32), %2:_(s16) = G_UNMERGE_VALUES %0
12+
13+
; CHECK: Bad machine code: G_UNMERGE_VALUES source operand does not match vector destination operands
14+
%3:_(<4 x s32>) = IMPLICIT_DEF
15+
%4:_(<3 x s32>), %5:_(<3 x s32>) = G_UNMERGE_VALUES %3
16+
17+
; CHECK: Bad machine code: G_UNMERGE_VALUES source operand does not match vector destination operands
18+
%6:_(<2 x s16>), %7:_(<2 x s16>) = G_UNMERGE_VALUES %3
19+
20+
; CHECK: Bad machine code: G_UNMERGE_VALUES vector source operand does not match scalar destination operands
21+
%8:_(<2 x s32>) = IMPLICIT_DEF
22+
%9:_(s32), %10:_(s32), %11:_(s32) = G_UNMERGE_VALUES %8
23+
24+
; CHECK: Bad machine code: G_UNMERGE_VALUES vector source operand does not match scalar destination operands
25+
%12:_(s16), %13:_(s16) = G_UNMERGE_VALUES %8
26+
27+
; CHECK: Bad machine code: G_UNMERGE_VALUES scalar source operand does not match scalar destination operands
28+
%14:_(s64) = IMPLICIT_DEF
29+
%15:_(s16), %16:_(s16) = G_UNMERGE_VALUES %14
30+
31+
; CHECK: Bad machine code: G_UNMERGE_VALUES scalar source operand does not match scalar destination operands
32+
%17:_(s32), %18:_(s32), %19:_(s32) = G_UNMERGE_VALUES %14
33+
...

0 commit comments

Comments
 (0)