From e9e2ba05de573f926f1d054add7ddbf15eab178a Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 10 May 2010 21:26:24 +0000 Subject: [PATCH] Model some vld3 instructions with REG_SEQUENCE. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103437 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelDAGToDAG.cpp | 35 +++++++++++- lib/Target/ARM/NEONPreAllocPass.cpp | 82 +++++++++++++++++++---------- 2 files changed, 87 insertions(+), 30 deletions(-) diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index abc02e263e6..7f73556a244 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -1044,7 +1044,40 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs, const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain }; std::vector ResTys(NumVecs, VT); ResTys.push_back(MVT::Other); - return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5); + SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5); + if (!llvm::ModelWithRegSequence() || NumVecs < 2) + return VLd; + + assert(NumVecs <= 4); + SDValue V0 = SDValue(VLd, 0); + SDValue V1 = SDValue(VLd, 1); + SDValue RegSeq; + + if (NumVecs == 2) + RegSeq = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); + else { + SDValue V2 = SDValue(VLd, 2); + SDValue V3 = (NumVecs == 3) + ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) + : SDValue(VLd, 3); + RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); + } + + SDValue D0 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, VT, RegSeq); + ReplaceUses(SDValue(N, 0), D0); + SDValue D1 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, VT, RegSeq); + ReplaceUses(SDValue(N, 1), D1); + + if (NumVecs > 2) { + SDValue D2 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_2, dl, VT, RegSeq); + ReplaceUses(SDValue(N, 2), D2); + } + if (NumVecs > 3) { + SDValue D3 = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_3, dl, VT, RegSeq); + ReplaceUses(SDValue(N, 3), D3); + } + ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, NumVecs)); + return NULL; } EVT RegVT = GetNEONSubregVT(VT); diff --git a/lib/Target/ARM/NEONPreAllocPass.cpp b/lib/Target/ARM/NEONPreAllocPass.cpp index a8df364d6d9..538247a8924 100644 --- a/lib/Target/ARM/NEONPreAllocPass.cpp +++ b/lib/Target/ARM/NEONPreAllocPass.cpp @@ -33,7 +33,7 @@ namespace { private: bool FormsRegSequence(MachineInstr *MI, - unsigned FirstOpnd, unsigned NumRegs); + unsigned FirstOpnd, unsigned NumRegs) const; bool PreAllocNEONRegisters(MachineBasicBlock &MBB); }; @@ -338,18 +338,22 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs, return false; } -bool NEONPreAllocPass::FormsRegSequence(MachineInstr *MI, - unsigned FirstOpnd, unsigned NumRegs) { - MachineInstr *RegSeq = 0; - unsigned LastSrcReg = 0; - unsigned LastSubIdx = 0; - for (unsigned R = 0; R < NumRegs; ++R) { - MachineOperand &MO = MI->getOperand(FirstOpnd + R); - assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand"); - unsigned VirtReg = MO.getReg(); - assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && - "expected a virtual register"); - if (MO.isDef()) { +bool +NEONPreAllocPass::FormsRegSequence(MachineInstr *MI, + unsigned FirstOpnd, unsigned NumRegs) const { + MachineOperand &FMO = MI->getOperand(FirstOpnd); + assert(FMO.isReg() && FMO.getSubReg() == 0 && "unexpected operand"); + unsigned VirtReg = FMO.getReg(); + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "expected a virtual register"); + if (FMO.isDef()) { + MachineInstr *RegSeq = 0; + for (unsigned R = 0; R < NumRegs; ++R) { + const MachineOperand &MO = MI->getOperand(FirstOpnd + R); + assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand"); + unsigned VirtReg = MO.getReg(); + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "expected a virtual register"); // Feeding into a REG_SEQUENCE. if (!MRI->hasOneNonDBGUse(VirtReg)) return false; @@ -359,25 +363,45 @@ bool NEONPreAllocPass::FormsRegSequence(MachineInstr *MI, if (RegSeq && RegSeq != UseMI) return false; RegSeq = UseMI; - } else { - // Extracting from a Q or QQ register. + } + + // Make sure trailing operands of REG_SEQUENCE are undef. + unsigned NumExps = (RegSeq->getNumOperands() - 1) / 2; + for (unsigned i = NumRegs * 2 + 1; i < NumExps; i += 2) { + const MachineOperand &MO = RegSeq->getOperand(i); + unsigned VirtReg = MO.getReg(); MachineInstr *DefMI = MRI->getVRegDef(VirtReg); - if (!DefMI || !DefMI->isExtractSubreg()) - return false; - VirtReg = DefMI->getOperand(1).getReg(); - if (LastSrcReg && LastSrcReg != VirtReg) + if (!DefMI || !DefMI->isImplicitDef()) return false; - const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); - if (NumRegs == 2) { - if (RC != ARM::QPRRegisterClass) - return false; - } else if (RC != ARM::QQPRRegisterClass) - return false; - unsigned SubIdx = DefMI->getOperand(2).getImm(); - if (LastSubIdx && LastSubIdx != SubIdx-1) - return false; - LastSubIdx = SubIdx; } + return true; + } + + unsigned LastSrcReg = 0; + unsigned LastSubIdx = 0; + for (unsigned R = 0; R < NumRegs; ++R) { + const MachineOperand &MO = MI->getOperand(FirstOpnd + R); + assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand"); + unsigned VirtReg = MO.getReg(); + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "expected a virtual register"); + // Extracting from a Q or QQ register. + MachineInstr *DefMI = MRI->getVRegDef(VirtReg); + if (!DefMI || !DefMI->isExtractSubreg()) + return false; + VirtReg = DefMI->getOperand(1).getReg(); + if (LastSrcReg && LastSrcReg != VirtReg) + return false; + const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); + if (NumRegs == 2) { + if (RC != ARM::QPRRegisterClass) + return false; + } else if (RC != ARM::QQPRRegisterClass) + return false; + unsigned SubIdx = DefMI->getOperand(2).getImm(); + if (LastSubIdx && LastSubIdx != SubIdx-1) + return false; + LastSubIdx = SubIdx; } return true; } -- 2.34.1