diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1239,17 +1239,38 @@ 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/MachineVerifier/test_g_unmerge_values.mir b/llvm/test/MachineVerifier/test_g_unmerge_values.mir new file mode 100644 --- /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 +...