summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2010-05-10 21:26:24 +0000
committerEvan Cheng <evan.cheng@apple.com>2010-05-10 21:26:24 +0000
commite9e2ba05de573f926f1d054add7ddbf15eab178a (patch)
tree7af93b1efe94f532a23885096ca63a9ac37c1d01
parent9cc9bfaf86510790c36198b033f241635614a8d0 (diff)
downloadexternal_llvm-e9e2ba05de573f926f1d054add7ddbf15eab178a.zip
external_llvm-e9e2ba05de573f926f1d054add7ddbf15eab178a.tar.gz
external_llvm-e9e2ba05de573f926f1d054add7ddbf15eab178a.tar.bz2
Model some vld3 instructions with REG_SEQUENCE.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103437 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp35
-rw-r--r--lib/Target/ARM/NEONPreAllocPass.cpp82
2 files changed, 87 insertions, 30 deletions
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index abc02e2..7f73556 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<EVT> 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 a8df364..538247a 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;
}