Index: llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -222,6 +222,8 @@ MachineIRBuilderState State; + unsigned getOpcodeForMerge(const DstOp &DstOp, ArrayRef SrcOps) const; + protected: void validateTruncExt(const LLT Dst, const LLT Src, bool IsExtend); @@ -966,16 +968,22 @@ MachineInstrBuilder buildUndef(const DstOp &Res); /// Build and insert \p Res = G_MERGE_VALUES \p Op0, ... + /// or \p Res = G_BUILD_VECTOR \p Op0, ... + /// or \p Res = G_CONCAT_VECTORS \p Op0, ... /// /// G_MERGE_VALUES combines the input elements contiguously into a larger - /// register. + /// register. It is used when the destination register is not a vector. + /// G_BUILD_VECTOR combines scalar inputs into a vector register. + /// G_CONCAT_VECTORS combines vector inputs into a vector register. /// /// \pre setBasicBlock or setMI must have been called. /// \pre The entire register \p Res (and no more) must be covered by the input /// registers. /// \pre The type of all \p Ops registers must be identical. /// - /// \return a MachineInstrBuilder for the newly created instruction. + /// \return a MachineInstrBuilder for the newly created instruction. The + /// opcode of the new instruction will depend on the types of both + /// the destination and the sources. MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef Ops); MachineInstrBuilder buildMerge(const DstOp &Res, std::initializer_list Ops); Index: llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -604,14 +604,25 @@ // sufficiently large SmallVector to not go through the heap. SmallVector TmpVec(Ops.begin(), Ops.end()); assert(TmpVec.size() > 1); - return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec); + return buildInstr(getOpcodeForMerge(Res, TmpVec), Res, TmpVec); } MachineInstrBuilder MachineIRBuilder::buildMerge(const DstOp &Res, std::initializer_list Ops) { assert(Ops.size() > 1); - return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, Ops); + return buildInstr(getOpcodeForMerge(Res, Ops), Res, Ops); +} + +unsigned MachineIRBuilder::getOpcodeForMerge(const DstOp &DstOp, + ArrayRef SrcOps) const { + if (DstOp.getLLTTy(*getMRI()).isVector()) { + if (SrcOps[0].getLLTTy(*getMRI()).isVector()) + return TargetOpcode::G_CONCAT_VECTORS; + return TargetOpcode::G_BUILD_VECTOR; + } + + return TargetOpcode::G_MERGE_VALUES; } MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef Res, @@ -674,6 +685,9 @@ // we need some temporary storage for the DstOp objects. Here we use a // sufficiently large SmallVector to not go through the heap. SmallVector TmpVec(Ops.begin(), Ops.end()); + if (TmpVec[0].getLLTTy(*getMRI()).getSizeInBits() == + Res.getLLTTy(*getMRI()).getElementType().getSizeInBits()) + return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec); return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec); } @@ -1159,7 +1173,7 @@ break; } case TargetOpcode::G_MERGE_VALUES: { - assert(!SrcOps.empty() && "invalid trivial sequence"); + assert(SrcOps.size() >= 2 && "invalid trivial sequence"); assert(DstOps.size() == 1 && "Invalid Dst"); assert(llvm::all_of(SrcOps, [&, this](const SrcOp &Op) { @@ -1171,13 +1185,8 @@ SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() == DstOps[0].getLLTTy(*getMRI()).getSizeInBits() && "input operands do not cover output register"); - if (SrcOps.size() == 1) - return buildCast(DstOps[0], SrcOps[0]); - if (DstOps[0].getLLTTy(*getMRI()).isVector()) { - if (SrcOps[0].getLLTTy(*getMRI()).isVector()) - return buildInstr(TargetOpcode::G_CONCAT_VECTORS, DstOps, SrcOps); - return buildInstr(TargetOpcode::G_BUILD_VECTOR, DstOps, SrcOps); - } + assert(!DstOps[0].getLLTTy(*getMRI()).isVector() && + "vectors should be built with G_CONCAT_VECTOR or G_BUILD_VECTOR"); break; } case TargetOpcode::G_EXTRACT_VECTOR_ELT: { @@ -1237,9 +1246,6 @@ SrcOps[0].getLLTTy(*getMRI()); }) && "type mismatch in input list"); - if (SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() == - DstOps[0].getLLTTy(*getMRI()).getElementType().getSizeInBits()) - return buildInstr(TargetOpcode::G_BUILD_VECTOR, DstOps, SrcOps); break; } case TargetOpcode::G_CONCAT_VECTORS: {