diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 83141f68431d..31ffdc0e2e78 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -299,6 +299,8 @@ private: bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder); + bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder); + // Stubs to keep the compiler happy while we implement the rest of the // translation. bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { @@ -337,9 +339,6 @@ private: bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } /// @} diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 64f4ec8dd44f..de3796cd4ee5 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -537,4 +537,11 @@ def G_EXTRACT_VECTOR_ELT : Instruction { let hasSideEffects = 0; } +// Generic shufflevector. +def G_SHUFFLE_VECTOR: Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask); + let hasSideEffects = 0; +} + // TODO: Add the other generic opcodes. diff --git a/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def index e3ae2fae83ee..96db6e0a9769 100644 --- a/llvm/include/llvm/Target/TargetOpcodes.def +++ b/llvm/include/llvm/Target/TargetOpcodes.def @@ -401,12 +401,15 @@ HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT) /// Generic extractelement. HANDLE_TARGET_OPCODE(G_EXTRACT_VECTOR_ELT) +/// Generic shufflevector. +HANDLE_TARGET_OPCODE(G_SHUFFLE_VECTOR) + // TODO: Add more generic opcodes as we move along. /// Marker for the end of the generic opcode. /// This is used to check if an opcode is in the range of the /// generic opcodes. -HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_EXTRACT_VECTOR_ELT) +HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_SHUFFLE_VECTOR) /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 0f97469d453e..b6e6fbd03d02 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1005,6 +1005,16 @@ bool IRTranslator::translateExtractElement(const User &U, return true; } +bool IRTranslator::translateShuffleVector(const User &U, + MachineIRBuilder &MIRBuilder) { + MIRBuilder.buildInstr(TargetOpcode::G_SHUFFLE_VECTOR) + .addDef(getOrCreateVReg(U)) + .addUse(getOrCreateVReg(*U.getOperand(0))) + .addUse(getOrCreateVReg(*U.getOperand(1))) + .addUse(getOrCreateVReg(*U.getOperand(2))); + return true; +} + bool IRTranslator::translatePHI(const User &U, MachineIRBuilder &MIRBuilder) { const PHINode &PI = cast(U); auto MIB = MIRBuilder.buildInstr(TargetOpcode::PHI); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index db85d41c37f6..a4352efc64a3 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -1411,3 +1411,111 @@ define float @test_different_call_conv_target(float %x) { %res = call ghccc float @different_call_conv_target(float %x) ret float %res } + +define <2 x i32> @test_shufflevector_s32_v2s32(i32 %arg) { +; CHECK-LABEL: name: test_shufflevector_s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[UNDEF:%[0-9]+]](s32) = IMPLICIT_DEF +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C0]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 + %res = shufflevector <1 x i32> %vec, <1 x i32> undef, <2 x i32> zeroinitializer + ret <2 x i32> %res +} + +define i32 @test_shufflevector_v2s32_s32(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_s32 +; CHECK: [[ARG:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[RES:%[0-9]+]](s32) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[C1]](s32) +; CHECK: %w0 = COPY [[RES]](s32) + %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <1 x i32> + %res = extractelement <1 x i32> %vec, i32 0 + ret i32 %res +} + +define <2 x i32> @test_shufflevector_v2s32_v2s32(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C0]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> + ret <2 x i32> %res +} + +define i32 @test_shufflevector_v2s32_v3s32(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v3s32 +; CHECK: [[ARG:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[MASK:%[0-9]+]](<3 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C0]](s32), [[C1]](s32) +; CHECK: [[VEC:%[0-9]+]](<3 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[MASK]](<3 x s32>) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) + %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <3 x i32> + %res = extractelement <3 x i32> %vec, i32 0 + ret i32 %res +} + +define <4 x i32> @test_shufflevector_v2s32_v4s32(<2 x i32> %arg1, <2 x i32> %arg2) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v4s32 +; CHECK: [[ARG1:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[ARG2:%[0-9]+]](<2 x s32>) = COPY %d1 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[MASK:%[0-9]+]](<4 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C1]](s32), [[C2]](s32), [[C3]](s32) +; CHECK: [[VEC:%[0-9]+]](<4 x s32>) = G_SHUFFLE_VECTOR [[ARG1]](<2 x s32>), [[ARG2]], [[MASK]](<4 x s32>) +; CHECK: %q0 = COPY [[VEC]](<4 x s32>) + %res = shufflevector <2 x i32> %arg1, <2 x i32> %arg2, <4 x i32> + ret <4 x i32> %res +} + +define <2 x i32> @test_shufflevector_v4s32_v2s32(<4 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v4s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](<4 x s32>) = COPY %q0 +; CHECK: [[UNDEF:%[0-9]+]](<4 x s32>) = IMPLICIT_DEF +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C3]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<4 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + %res = shufflevector <4 x i32> %arg, <4 x i32> undef, <2 x i32> + ret <2 x i32> %res +} + + +define <16 x i8> @test_shufflevector_v8s8_v16s8(<8 x i8> %arg1, <8 x i8> %arg2) { +; CHECK-LABEL: name: test_shufflevector_v8s8_v16s8 +; CHECK: [[ARG1:%[0-9]+]](<8 x s8>) = COPY %d0 +; CHECK: [[ARG2:%[0-9]+]](<8 x s8>) = COPY %d1 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C8:%[0-9]+]](s32) = G_CONSTANT i32 8 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C9:%[0-9]+]](s32) = G_CONSTANT i32 9 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C10:%[0-9]+]](s32) = G_CONSTANT i32 10 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[C11:%[0-9]+]](s32) = G_CONSTANT i32 11 +; CHECK: [[C4:%[0-9]+]](s32) = G_CONSTANT i32 4 +; CHECK: [[C12:%[0-9]+]](s32) = G_CONSTANT i32 12 +; CHECK: [[C5:%[0-9]+]](s32) = G_CONSTANT i32 5 +; CHECK: [[C13:%[0-9]+]](s32) = G_CONSTANT i32 13 +; CHECK: [[C6:%[0-9]+]](s32) = G_CONSTANT i32 6 +; CHECK: [[C14:%[0-9]+]](s32) = G_CONSTANT i32 14 +; CHECK: [[C7:%[0-9]+]](s32) = G_CONSTANT i32 7 +; CHECK: [[C15:%[0-9]+]](s32) = G_CONSTANT i32 15 +; CHECK: [[MASK:%[0-9]+]](<16 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C8]](s32), [[C1]](s32), [[C9]](s32), [[C2]](s32), [[C10]](s32), [[C3]](s32), [[C11]](s32), [[C4]](s32), [[C12]](s32), [[C5]](s32), [[C13]](s32), [[C6]](s32), [[C14]](s32), [[C7]](s32), [[C15]](s32) +; CHECK: [[VEC:%[0-9]+]](<16 x s8>) = G_SHUFFLE_VECTOR [[ARG1]](<8 x s8>), [[ARG2]], [[MASK]](<16 x s32>) +; CHECK: %q0 = COPY [[VEC]](<16 x s8>) + %res = shufflevector <8 x i8> %arg1, <8 x i8> %arg2, <16 x i32> + ret <16 x i8> %res +} diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index d285bf3a3bb8..c73e386e6bf3 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -543,3 +543,83 @@ entry: %r = notail call arm_aapcscc float @different_call_conv_target(float %x) ret float %r } + +define i32 @test_shufflevector_s32_v2s32(i32 %arg) { +; CHECK-LABEL: name: test_shufflevector_s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](s32) = COPY %r0 +; CHECK: [[UNDEF:%[0-9]+]](s32) = IMPLICIT_DEF +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C0]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>) + %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 + %shuffle = shufflevector <1 x i32> %vec, <1 x i32> undef, <2 x i32> zeroinitializer + %res = extractelement <2 x i32> %shuffle, i32 0 + ret i32 %res +} + +define i32 @test_shufflevector_v2s32_v3s32(i32 %arg1, i32 %arg2) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v3s32 +; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %r0 +; CHECK: [[ARG2:%[0-9]+]](s32) = COPY %r1 +; CHECK: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[MASK:%[0-9]+]](<3 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C0]](s32), [[C1]](s32) +; CHECK: [[V1:%[0-9]+]](<2 x s32>) = G_INSERT_VECTOR_ELT [[UNDEF]], [[ARG1]](s32), [[C0]](s32) +; CHECK: [[V2:%[0-9]+]](<2 x s32>) = G_INSERT_VECTOR_ELT [[V1]], [[ARG2]](s32), [[C1]](s32) +; CHECK: [[VEC:%[0-9]+]](<3 x s32>) = G_SHUFFLE_VECTOR [[V2]](<2 x s32>), [[UNDEF]], [[MASK]](<3 x s32>) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) + %v1 = insertelement <2 x i32> undef, i32 %arg1, i32 0 + %v2 = insertelement <2 x i32> %v1, i32 %arg2, i32 1 + %shuffle = shufflevector <2 x i32> %v2, <2 x i32> undef, <3 x i32> + %res = extractelement <3 x i32> %shuffle, i32 0 + ret i32 %res +} + + +define i32 @test_shufflevector_v2s32_v4s32(i32 %arg1, i32 %arg2) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v4s32 +; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %r0 +; CHECK: [[ARG2:%[0-9]+]](s32) = COPY %r1 +; CHECK: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[MASK:%[0-9]+]](<4 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C0]](s32), [[C0]](s32), [[C0]](s32) +; CHECK: [[V1:%[0-9]+]](<2 x s32>) = G_INSERT_VECTOR_ELT [[UNDEF]], [[ARG1]](s32), [[C0]](s32) +; CHECK: [[V2:%[0-9]+]](<2 x s32>) = G_INSERT_VECTOR_ELT [[V1]], [[ARG2]](s32), [[C1]](s32) +; CHECK: [[VEC:%[0-9]+]](<4 x s32>) = G_SHUFFLE_VECTOR [[V2]](<2 x s32>), [[UNDEF]], [[MASK]](<4 x s32>) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<4 x s32>) + %v1 = insertelement <2 x i32> undef, i32 %arg1, i32 0 + %v2 = insertelement <2 x i32> %v1, i32 %arg2, i32 1 + %shuffle = shufflevector <2 x i32> %v2, <2 x i32> undef, <4 x i32> zeroinitializer + %res = extractelement <4 x i32> %shuffle, i32 0 + ret i32 %res +} + +define i32 @test_shufflevector_v4s32_v2s32(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) { +; CHECK-LABEL: name: test_shufflevector_v4s32_v2s32 +; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %r0 +; CHECK: [[ARG2:%[0-9]+]](s32) = COPY %r1 +; CHECK: [[ARG3:%[0-9]+]](s32) = COPY %r2 +; CHECK: [[ARG4:%[0-9]+]](s32) = COPY %r3 +; CHECK: [[UNDEF:%[0-9]+]](<4 x s32>) = IMPLICIT_DEF +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C3]](s32) +; CHECK: [[V1:%[0-9]+]](<4 x s32>) = G_INSERT_VECTOR_ELT [[UNDEF]], [[ARG1]](s32), [[C0]](s32) +; CHECK: [[V2:%[0-9]+]](<4 x s32>) = G_INSERT_VECTOR_ELT [[V1]], [[ARG2]](s32), [[C1]](s32) +; CHECK: [[V3:%[0-9]+]](<4 x s32>) = G_INSERT_VECTOR_ELT [[V2]], [[ARG3]](s32), [[C2]](s32) +; CHECK: [[V4:%[0-9]+]](<4 x s32>) = G_INSERT_VECTOR_ELT [[V3]], [[ARG4]](s32), [[C3]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[V4]](<4 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>) + %v1 = insertelement <4 x i32> undef, i32 %arg1, i32 0 + %v2 = insertelement <4 x i32> %v1, i32 %arg2, i32 1 + %v3 = insertelement <4 x i32> %v2, i32 %arg3, i32 2 + %v4 = insertelement <4 x i32> %v3, i32 %arg4, i32 3 + %shuffle = shufflevector <4 x i32> %v4, <4 x i32> undef, <2 x i32> + %res = extractelement <2 x i32> %shuffle, i32 0 + ret i32 %res +}