Index: include/llvm/CodeGen/GlobalISel/LegalizerHelper.h =================================================================== --- include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -85,6 +85,11 @@ LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + /// Legalize a vector instruction by splitting in to multiple scalar + /// components, each acting on the same scalar type as the original but + /// as scalar operations. + LegalizeResult scalarElementsVector(MachineInstr &MI, unsigned TypeIdx); + /// Expose MIRBuilder so clients can set their own RecordInsertInstruction /// functions MachineIRBuilder MIRBuilder; Index: include/llvm/CodeGen/GlobalISel/LegalizerInfo.h =================================================================== --- include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -69,6 +69,11 @@ /// this target. E.g. a SREM replaced by an SDIV and subtraction. Lower, + /// The (vector) operation should be implemented by splitting it in to + /// scalar operations. For example a <8 x s64> add will be implemented as + /// 8 separate s64 adds. + LowerScalar, + /// The operation should be implemented as a call to some kind of runtime /// support library. For example this usually happens on machines that don't /// support floating-point operations natively. @@ -362,6 +367,11 @@ return actionIf(LegalizeAction::FewerElements, Predicate, Mutation); } + /// Lower the element to scalar operations of the same element type + LegalizeRuleSet &lowerScalarFor(std::initializer_list Types) { + return actionFor(LegalizeAction::LowerScalar, Types); + } + /// The instruction is unsupported. LegalizeRuleSet &unsupported() { return actionIf(LegalizeAction::Unsupported, always); Index: lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -57,6 +57,9 @@ case FewerElements: DEBUG(dbgs() << ".. Reduce number of elements\n"); return fewerElementsVector(MI, Step.TypeIdx, Step.NewType); + case LowerScalar: + DEBUG(dbgs() << ".. Reduce vector to scalar\n"); + return scalarElementsVector(MI, Step.TypeIdx); case Custom: DEBUG(dbgs() << ".. Custom legalization\n"); return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized @@ -1044,3 +1047,56 @@ } } } +LegalizerHelper::LegalizeResult +LegalizerHelper::scalarElementsVector(MachineInstr &MI, unsigned TypeIdx) { + // FIXME: Don't know how to handle secondary types yet. + if (TypeIdx != 0) + return UnableToLegalize; + switch (MI.getOpcode()) { + default: + return UnableToLegalize; + case TargetOpcode::G_ADD: + case TargetOpcode::G_AND: + case TargetOpcode::G_MUL: + case TargetOpcode::G_OR: + case TargetOpcode::G_XOR: + case TargetOpcode::G_SUB: + case TargetOpcode::G_FADD: + case TargetOpcode::G_FSUB: + case TargetOpcode::G_FMUL: + case TargetOpcode::G_FDIV: + case TargetOpcode::G_FMA: + case TargetOpcode::G_FPOW: + case TargetOpcode::G_FREM: { + unsigned DstReg = MI.getOperand(0).getReg(); + LLT Type = MRI.getType(DstReg); + LLT NarrowTy = Type.getElementType(); + unsigned NarrowSize = NarrowTy.getSizeInBits(); + unsigned Size = Type.getSizeInBits(); + int NumParts = Size / NarrowSize; + // FIXME: Don't know how to handle the situation where the small vectors + // aren't all the same size yet. + if (Size % NarrowSize != 0) + return UnableToLegalize; + + MIRBuilder.setInstr(MI); + + SmallVector Src1Regs, Src2Regs, DstRegs; + extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); + extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); + + for (int i = 0; i < NumParts; ++i) { + unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); + MIRBuilder.buildInstr(MI.getOpcode()) + .addDef(DstReg) + .addUse(Src1Regs[i]) + .addUse(Src2Regs[i]); + DstRegs.push_back(DstReg); + } + + MIRBuilder.buildMerge(DstReg, DstRegs); + MI.eraseFromParent(); + return Legalized; + } + } +} Index: lib/CodeGen/GlobalISel/LegalizerInfo.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -399,6 +399,8 @@ case Libcall: case Custom: return {Size, Action}; + case LowerScalar: + return {1, LowerScalar}; case FewerElements: // FIXME: is this special case still needed and correct? // Special case for scalarization: Index: unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp =================================================================== --- unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp +++ unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp @@ -25,6 +25,7 @@ case WidenScalar: OS << "WidenScalar"; break; case FewerElements: OS << "FewerElements"; break; case MoreElements: OS << "MoreElements"; break; + case LowerScalar: OS << "LowerScalar"; break; case Libcall: OS << "Libcall"; break; case Custom: OS << "Custom"; break; case Unsupported: OS << "Unsupported"; break;