Index: include/llvm/Target/GenericOpcodes.td =================================================================== --- include/llvm/Target/GenericOpcodes.td +++ include/llvm/Target/GenericOpcodes.td @@ -499,8 +499,8 @@ // indexes. This will almost certainly be mapped to sub-register COPYs after // register banks have been selected. def G_UNMERGE_VALUES : Instruction { - let OutOperandList = (outs); - let InOperandList = (ins variable_ops); + let OutOperandList = (outs type0:$dst0, variable_ops); + let InOperandList = (ins type1:$src); let hasSideEffects = 0; } @@ -514,7 +514,7 @@ /// Concatenante multiple registers of the same size into a wider register. def G_MERGE_VALUES : Instruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins variable_ops); + let InOperandList = (ins type1:$src0, variable_ops); let hasSideEffects = 0; } Index: lib/CodeGen/GlobalISel/LegalizerInfo.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -64,6 +64,28 @@ setLegalizeScalarToDifferentSizeStrategy( TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall); setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}}); + + // Set default actions for G_MERGE_VALUES and G_UNMERGE_VALUES. + // TODO: Remove this once we have better support for vector types. + for (unsigned Op : + {TargetOpcode::G_MERGE_VALUES, TargetOpcode::G_UNMERGE_VALUES}) + for (unsigned TypeIdx : {0, 1}) { + setScalarAction(Op, TypeIdx, {{1, Legal}}); + setScalarInVectorAction(Op, TypeIdx, + {{1, Legal}, + {2, Unsupported}, + {4, Unsupported}, + {8, Legal}, + {9, Unsupported}, + {16, Legal}, + {17, Unsupported}, + {32, Legal}, + {33, Unsupported}, + {64, Legal}, + {65, Unsupported}}); + for (unsigned Size : {1, 8, 16, 32, 64}) + setVectorNumElementAction(Op, TypeIdx, Size, {{1, Legal}}); + } } void LegalizerInfo::computeTables() { @@ -167,13 +189,6 @@ assert(TablesInitialized && "backend forgot to call computeTables"); // These *have* to be implemented for now, they're the fundamental basis of // how everything else is transformed. - - // FIXME: the long-term plan calls for expansion in terms of load/store (if - // they're not legal). - if (Aspect.Opcode == TargetOpcode::G_MERGE_VALUES || - Aspect.Opcode == TargetOpcode::G_UNMERGE_VALUES) - return std::make_pair(Legal, Aspect.Type); - if (Aspect.Type.isScalar() || Aspect.Type.isPointer()) return findScalarLegalAction(Aspect); assert(Aspect.Type.isVector()); @@ -198,7 +213,15 @@ SeenTypes.set(TypeIdx); - LLT Ty = MRI.getType(MI.getOperand(i).getReg()); + unsigned Op = MI.getOperand(i).getReg(); + // For G_MERGE_VALUES and G_UNMERGE_VALUES, get the last operand + // if TypeIdx == 1 as they have variable number of operands. + if ((MI.getOpcode() == TargetOpcode::G_MERGE_VALUES || + MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) && + TypeIdx == 1) { + Op = MI.getOperand(MI.getNumOperands() - 1).getReg(); + } + LLT Ty = MRI.getType(Op); auto Action = getAction({MI.getOpcode(), TypeIdx, Ty}); if (Action.first != Legal) return std::make_tuple(Action.first, TypeIdx, Action.second); Index: test/CodeGen/AArch64/GlobalISel/legalize-combines.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/legalize-combines.mir +++ test/CodeGen/AArch64/GlobalISel/legalize-combines.mir @@ -8,7 +8,6 @@ define void @test_combines_3() { ret void } define void @test_combines_4() { ret void } define void @test_combines_5() { ret void } - define void @test_combines_6() { ret void } ... --- @@ -84,22 +83,3 @@ %3:_(s32), %4:_(s32) = G_UNMERGE_VALUES %2 %5:_(s32) = G_ADD %3, %4 ... - ---- -name: test_combines_6 -body: | - bb.0: - liveins: %w0 - - ; Check that we replace all the uses of a G_EXTRACT. - ; CHECK-LABEL: name: test_combines_6 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY %w0 - ; CHECK: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY]] - ; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[MUL]] - %0:_(s32) = COPY %w0 - - %1:_(s32) = G_MERGE_VALUES %0 - %2:_(s32) = G_UNMERGE_VALUES %1 - %3:_(s32) = G_MUL %2, %2 - %4:_(s32) = G_ADD %2, %3 -... Index: test/CodeGen/AArch64/GlobalISel/legalize-merge-values.mir =================================================================== --- /dev/null +++ test/CodeGen/AArch64/GlobalISel/legalize-merge-values.mir @@ -0,0 +1,28 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel -global-isel-abort=0 -pass-remarks-missed='gisel*' %s -o - 2>&1 | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_merge_v2s4() { + ret void + } +... + +--- +name: test_merge_v2s4 +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } +body: | + bb.0: + %0(s64) = G_CONSTANT i64 0 + %1(s4) = G_TRUNC %0(s64) + ; CHECK: unable to legalize instruction: %vreg2(<2 x s4>) = G_MERGE_VALUES + %2(<2 x s4>) = G_MERGE_VALUES %1(s4), %1(s4), %1(s4), %1(s4) + %3(s8) = G_BITCAST %2(<2 x s4>) + %4(s64) = G_ANYEXT %3(s8) + %x0 = COPY %4(s64) +... Index: test/CodeGen/AArch64/GlobalISel/legalize-unmerge-values.mir =================================================================== --- /dev/null +++ test/CodeGen/AArch64/GlobalISel/legalize-unmerge-values.mir @@ -0,0 +1,29 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel -global-isel-abort=0 -pass-remarks-missed='gisel*' %s -o - 2>&1 | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_unmerge_v2s4() { + ret void + } +... + +--- +name: test_unmerge_v2s4 +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } + - { id: 5, class: _ } +body: | + bb.0: + %0(s16) = G_CONSTANT i16 0 + ; CHECK: unable to legalize instruction:{{.*}}G_UNMERGE_VALUES + %1(<2 x s4>), %2(<2 x s4>)= G_UNMERGE_VALUES %0(s16) + %3(s8) = G_BITCAST %1(<2 x s4>) + %5(s64) = G_ANYEXT %4(s8) + %x0 = COPY %5(s64) + +... Index: test/CodeGen/AArch64/GlobalISel/no-regclass.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/no-regclass.mir +++ test/CodeGen/AArch64/GlobalISel/no-regclass.mir @@ -25,7 +25,7 @@ ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %w0 ; CHECK: %w0 = COPY [[COPY]] %0:gpr(s32) = COPY %w0 - %1:gpr(s32) = G_MERGE_VALUES %0(s32) - %2:gpr(s32) = G_UNMERGE_VALUES %1(s32) + %1:gpr(s64) = G_MERGE_VALUES %0(s32), %0(s32) + %2:gpr(s32), %3:gpr(s32) = G_UNMERGE_VALUES %1(s64) %w0 = COPY %2(s32) ...