summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2019-03-11 22:18:01 +0000
committerJessica Paquette <jpaquette@apple.com>2019-03-11 22:18:01 +0000
commit607774c960dbaf32773e2ddae72190f6e48d9d60 (patch)
tree88bbddd28e2e2a25dcab2ef14a2f30b10f1e587c /llvm/lib
parentaedec3f68410726a234f1e4072c1f6655ba9bbd3 (diff)
downloadbcm5719-llvm-607774c960dbaf32773e2ddae72190f6e48d9d60.tar.gz
bcm5719-llvm-607774c960dbaf32773e2ddae72190f6e48d9d60.zip
Recommit "[GlobalISel][AArch64] Add selection support for G_EXTRACT_VECTOR_ELT"
After r355865, we should be able to safely select G_EXTRACT_VECTOR_ELT without running into any problematic intrinsics. Also add a fix for lane copies, which don't support index 0. llvm-svn: 355871
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp153
-rw-r--r--llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp3
-rw-r--r--llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp8
3 files changed, 146 insertions, 18 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
index 41f4eb9563a..869cc143496 100644
--- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
@@ -78,6 +78,7 @@ private:
void collectShuffleMaskIndices(MachineInstr &I, MachineRegisterInfo &MRI,
SmallVectorImpl<int> &Idxs) const;
bool selectShuffleVector(MachineInstr &I, MachineRegisterInfo &MRI) const;
+ bool selectExtractElt(MachineInstr &I, MachineRegisterInfo &MRI) const;
unsigned emitConstantPoolEntry(Constant *CPVal, MachineFunction &MF) const;
MachineInstr *emitLoadFromConstantPool(Constant *CPVal,
@@ -1709,6 +1710,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
return selectUnmergeValues(I, MRI);
case TargetOpcode::G_SHUFFLE_VECTOR:
return selectShuffleVector(I, MRI);
+ case TargetOpcode::G_EXTRACT_VECTOR_ELT:
+ return selectExtractElt(I, MRI);
}
return false;
@@ -1787,6 +1790,138 @@ bool AArch64InstructionSelector::selectMergeValues(
return true;
}
+static bool getLaneCopyOpcode(unsigned &CopyOpc, unsigned &ExtractSubReg,
+ const unsigned EltSize) {
+ // Choose a lane copy opcode and subregister based off of the size of the
+ // vector's elements.
+ switch (EltSize) {
+ case 16:
+ CopyOpc = AArch64::CPYi16;
+ ExtractSubReg = AArch64::hsub;
+ break;
+ case 32:
+ CopyOpc = AArch64::CPYi32;
+ ExtractSubReg = AArch64::ssub;
+ break;
+ case 64:
+ CopyOpc = AArch64::CPYi64;
+ ExtractSubReg = AArch64::dsub;
+ break;
+ default:
+ // Unknown size, bail out.
+ LLVM_DEBUG(dbgs() << "Elt size '" << EltSize << "' unsupported.\n");
+ return false;
+ }
+ return true;
+}
+
+bool AArch64InstructionSelector::selectExtractElt(
+ MachineInstr &I, MachineRegisterInfo &MRI) const {
+ assert(I.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT &&
+ "unexpected opcode!");
+ unsigned DstReg = I.getOperand(0).getReg();
+ const LLT NarrowTy = MRI.getType(DstReg);
+ const unsigned SrcReg = I.getOperand(1).getReg();
+ const LLT WideTy = MRI.getType(SrcReg);
+
+ assert(WideTy.getSizeInBits() >= NarrowTy.getSizeInBits() &&
+ "source register size too small!");
+ assert(NarrowTy.isScalar() && "cannot extract vector into vector!");
+
+ // Need the lane index to determine the correct copy opcode.
+ MachineOperand &LaneIdxOp = I.getOperand(2);
+ assert(LaneIdxOp.isReg() && "Lane index operand was not a register?");
+
+ if (RBI.getRegBank(DstReg, MRI, TRI)->getID() != AArch64::FPRRegBankID) {
+ LLVM_DEBUG(dbgs() << "Cannot extract into GPR.\n");
+ return false;
+ }
+
+ // Find the instruction that defines the constant to extract from. There could
+ // be any number of copies between the instruction and the definition of the
+ // index. Skip them.
+ MachineInstr *LaneDefInst = nullptr;
+ for (LaneDefInst = MRI.getVRegDef(LaneIdxOp.getReg());
+ LaneDefInst && LaneDefInst->isCopy();
+ LaneDefInst = MRI.getVRegDef(LaneDefInst->getOperand(1).getReg())) {
+ }
+
+ // Did we find a def in the first place? If not, bail.
+ if (!LaneDefInst) {
+ LLVM_DEBUG(dbgs() << "Did not find VReg definition for " << LaneIdxOp
+ << "\n");
+ return false;
+ }
+
+ // TODO: Handle extracts that don't use G_CONSTANT.
+ if (LaneDefInst->getOpcode() != TargetOpcode::G_CONSTANT) {
+ LLVM_DEBUG(dbgs() << "VRegs defined by anything other than G_CONSTANT "
+ "currently unsupported.\n");
+ return false;
+ }
+
+ unsigned LaneIdx = LaneDefInst->getOperand(1).getCImm()->getLimitedValue();
+ unsigned CopyOpc = 0;
+ unsigned ExtractSubReg = 0;
+ if (!getLaneCopyOpcode(CopyOpc, ExtractSubReg, NarrowTy.getSizeInBits())) {
+ LLVM_DEBUG(
+ dbgs() << "Couldn't determine lane copy opcode for instruction.\n");
+ return false;
+ }
+
+ const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
+ const TargetRegisterClass *DstRC =
+ getRegClassForTypeOnBank(NarrowTy, DstRB, RBI, true);
+ if (!DstRC) {
+ LLVM_DEBUG(dbgs() << "Could not determine destination register class.\n");
+ return false;
+ }
+
+ const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
+ const TargetRegisterClass *SrcRC =
+ getRegClassForTypeOnBank(WideTy, SrcRB, RBI, true);
+ if (!SrcRC) {
+ LLVM_DEBUG(dbgs() << "Could not determine source register class.\n");
+ return false;
+ }
+
+ // The register that we're going to copy into.
+ unsigned InsertReg = SrcReg;
+ MachineIRBuilder MIRBuilder(I);
+
+ // If the lane index is 0, we just use a subregister COPY.
+ if (LaneIdx == 0) {
+ unsigned CopyTo = I.getOperand(0).getReg();
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
+ CopyTo)
+ .addUse(SrcReg, 0, ExtractSubReg);
+ RBI.constrainGenericRegister(CopyTo, *DstRC, MRI);
+ I.eraseFromParent();
+ return true;
+ }
+
+ // Lane copies require 128-bit wide registers. If we're dealing with an
+ // unpacked vector, then we need to move up to that width. Insert an implicit
+ // def and a subregister insert to get us there.
+ if (WideTy.getSizeInBits() != 128) {
+ MachineInstr *ScalarToVector = emitScalarToVector(
+ WideTy.getSizeInBits(), &AArch64::FPR128RegClass, SrcReg, MIRBuilder);
+ if (!ScalarToVector)
+ return false;
+ InsertReg = ScalarToVector->getOperand(0).getReg();
+ }
+
+ MachineInstr *LaneCopyMI =
+ MIRBuilder.buildInstr(CopyOpc, {DstReg}, {InsertReg}).addImm(LaneIdx);
+ constrainSelectedInstRegOperands(*LaneCopyMI, TII, TRI, RBI);
+
+ // Make sure that we actually constrain the initial copy.
+ RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
+
+ I.eraseFromParent();
+ return true;
+}
+
bool AArch64InstructionSelector::selectUnmergeValues(
MachineInstr &I, MachineRegisterInfo &MRI) const {
assert(I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
@@ -1823,24 +1958,8 @@ bool AArch64InstructionSelector::selectUnmergeValues(
// vector's elements.
unsigned CopyOpc = 0;
unsigned ExtractSubReg = 0;
- switch (NarrowTy.getSizeInBits()) {
- case 16:
- CopyOpc = AArch64::CPYi16;
- ExtractSubReg = AArch64::hsub;
- break;
- case 32:
- CopyOpc = AArch64::CPYi32;
- ExtractSubReg = AArch64::ssub;
- break;
- case 64:
- CopyOpc = AArch64::CPYi64;
- ExtractSubReg = AArch64::dsub;
- break;
- default:
- // Unknown size, bail out.
- LLVM_DEBUG(dbgs() << "NarrowTy had unsupported size.\n");
+ if (!getLaneCopyOpcode(CopyOpc, ExtractSubReg, NarrowTy.getSizeInBits()))
return false;
- }
// Set up for the lane copies.
MachineBasicBlock &MBB = *I.getParent();
diff --git a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp
index c473dc490c5..4a2f28117ec 100644
--- a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp
@@ -446,7 +446,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) {
.minScalar(2, s64)
.legalIf([=](const LegalityQuery &Query) {
const LLT &VecTy = Query.Types[1];
- return VecTy == v4s32 || VecTy == v2s64;
+ return VecTy == v2s16 || VecTy == v4s16 || VecTy == v4s32 ||
+ VecTy == v2s64 || VecTy == v2s32;
});
getActionDefinitionsBuilder(G_BUILD_VECTOR)
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
index 08cf6859f05..e4aebf4dbfe 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
@@ -689,6 +689,14 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
}
break;
}
+ case TargetOpcode::G_EXTRACT_VECTOR_ELT:
+ // Destination and source need to be FPRs.
+ OpRegBankIdx[0] = PMI_FirstFPR;
+ OpRegBankIdx[1] = PMI_FirstFPR;
+
+ // Index needs to be a GPR.
+ OpRegBankIdx[2] = PMI_FirstGPR;
+ break;
case TargetOpcode::G_BUILD_VECTOR:
// If the first source operand belongs to a FPR register bank, then make
OpenPOWER on IntegriCloud