From d3ffd47df94b362ebf52c0681bc2cdcfef00b98f Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Fri, 29 Mar 2019 21:39:36 +0000 Subject: [GlobalISel][AArch64] Add isel support for G_INSERT_VECTOR_ELT on v2s32s This adds support for v2s32 vector inserts, and updates the selection + regbankselect tests for G_INSERT_VECTOR_ELT. Differential Revision: https://reviews.llvm.org/D59910 llvm-svn: 357318 --- .../Target/AArch64/AArch64InstructionSelector.cpp | 51 +++++++++++++++++++--- llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp | 3 +- 2 files changed, 46 insertions(+), 8 deletions(-) (limited to 'llvm/lib/Target') diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index cd80518f900..f1274d7fa22 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -2561,11 +2561,7 @@ bool AArch64InstructionSelector::selectInsertElt( // Get information on the destination. unsigned DstReg = I.getOperand(0).getReg(); const LLT DstTy = MRI.getType(DstReg); - if (DstTy.getSizeInBits() < 128) { - // TODO: Handle unpacked vectors. - LLVM_DEBUG(dbgs() << "Unpacked vectors not supported yet!"); - return false; - } + unsigned VecSize = DstTy.getSizeInBits(); // Get information on the element we want to insert into the destination. unsigned EltReg = I.getOperand(2).getReg(); @@ -2585,7 +2581,50 @@ bool AArch64InstructionSelector::selectInsertElt( unsigned SrcReg = I.getOperand(1).getReg(); const RegisterBank &EltRB = *RBI.getRegBank(EltReg, MRI, TRI); MachineIRBuilder MIRBuilder(I); - emitLaneInsert(DstReg, SrcReg, EltReg, LaneIdx, EltRB, MIRBuilder); + + if (VecSize < 128) { + // If the vector we're inserting into is smaller than 128 bits, widen it + // to 128 to do the insert. + MachineInstr *ScalarToVec = emitScalarToVector( + VecSize, &AArch64::FPR128RegClass, SrcReg, MIRBuilder); + if (!ScalarToVec) + return false; + SrcReg = ScalarToVec->getOperand(0).getReg(); + } + + // Create an insert into a new FPR128 register. + // Note that if our vector is already 128 bits, we end up emitting an extra + // register. + MachineInstr *InsMI = + emitLaneInsert(None, SrcReg, EltReg, LaneIdx, EltRB, MIRBuilder); + + if (VecSize < 128) { + // If we had to widen to perform the insert, then we have to demote back to + // the original size to get the result we want. + unsigned DemoteVec = InsMI->getOperand(0).getReg(); + const TargetRegisterClass *RC = + getMinClassForRegBank(*RBI.getRegBank(DemoteVec, MRI, TRI), VecSize); + if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) { + LLVM_DEBUG(dbgs() << "Unsupported register class!\n"); + return false; + } + unsigned SubReg = 0; + if (!getSubRegForClass(RC, TRI, SubReg)) + return false; + if (SubReg != AArch64::ssub && SubReg != AArch64::dsub) { + LLVM_DEBUG(dbgs() << "Unsupported destination size! (" << VecSize + << "\n"); + return false; + } + MIRBuilder.buildInstr(TargetOpcode::COPY, {DstReg}, {}) + .addReg(DemoteVec, 0, SubReg); + RBI.constrainGenericRegister(DstReg, *RC, MRI); + } else { + // No widening needed. + InsMI->getOperand(0).setReg(DstReg); + constrainSelectedInstRegOperands(*InsMI, TII, TRI, RBI); + } + I.eraseFromParent(); return true; } diff --git a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp index b05e2afb8aa..854355c619c 100644 --- a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -448,9 +448,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) { getActionDefinitionsBuilder(G_INSERT_VECTOR_ELT) .legalIf([=](const LegalityQuery &Query) { const LLT &VecTy = Query.Types[0]; - // TODO: Support destination sizes of < 128 bits. // TODO: Support s8 and s16 - return VecTy == v4s32 || VecTy == v2s64; + return VecTy == v2s32 || VecTy == v4s32 || VecTy == v2s64; }); getActionDefinitionsBuilder(G_BUILD_VECTOR) -- cgit v1.2.3