aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@apple.com>2010-09-16 00:31:02 +0000
committerBob Wilson <bob.wilson@apple.com>2010-09-16 00:31:02 +0000
commit9d4ebc0eb80c770aab5b51ca459748a6ac8f1699 (patch)
treeb935119fa11d3141ce99854e3b70be957fa6e104
parentcb86def1c2084f2b1c72fd04e5384d472e7cf3a0 (diff)
Change VLDMQ and VSTMQ to be pseudo instructions. They are expanded after
register allocation to VLDMD and VSTMD respectively. This avoids using the dregpair operand modifier. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114047 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp50
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td11
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td24
3 files changed, 70 insertions, 15 deletions
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 79fcfe8d1c..4a3402fff1 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -640,6 +640,56 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
MI.eraseFromParent();
}
+ case ARM::VLDMQ: {
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::VLDMD));
+ unsigned OpIdx = 0;
+ // Grab the Q register destination.
+ bool DstIsDead = MI.getOperand(OpIdx).isDead();
+ unsigned DstReg = MI.getOperand(OpIdx++).getReg();
+ // Copy the addrmode4 operands.
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ // Copy the predicate operands.
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ // Add the destination operands (D subregs).
+ unsigned D0 = TRI->getSubReg(DstReg, ARM::dsub_0);
+ unsigned D1 = TRI->getSubReg(DstReg, ARM::dsub_1);
+ MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
+ // Add an implicit def for the super-register.
+ MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
+ TransferImpOps(MI, MIB, MIB);
+ MI.eraseFromParent();
+ break;
+ }
+
+ case ARM::VSTMQ: {
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::VSTMD));
+ unsigned OpIdx = 0;
+ // Grab the Q register source.
+ bool SrcIsKill = MI.getOperand(OpIdx).isKill();
+ unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
+ // Copy the addrmode4 operands.
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ // Copy the predicate operands.
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ MIB.addOperand(MI.getOperand(OpIdx++));
+ // Add the source operands (D subregs).
+ unsigned D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
+ unsigned D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);
+ MIB.addReg(D0).addReg(D1);
+ if (SrcIsKill)
+ // Add an implicit kill for the Q register.
+ (*MIB).addRegisterKilled(SrcReg, TRI, true);
+ TransferImpOps(MI, MIB, MIB);
+ MI.eraseFromParent();
+ break;
+ }
+
case ARM::VLD1q8Pseudo:
case ARM::VLD1q16Pseudo:
case ARM::VLD1q32Pseudo:
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 9610427bcb..7c25ae99b9 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -1331,6 +1331,17 @@ class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
let Inst{11-8} = 0b1010;
}
+// VFP Load / store multiple pseudo instructions.
+class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr,
+ list<dag> pattern>
+ : InstARM<AddrMode4, Size4Bytes, IndexModeNone, Pseudo, VFPNeonDomain,
+ cstr, itin> {
+ let OutOperandList = oops;
+ let InOperandList = !con(iops, (ins pred:$p));
+ let Pattern = pattern;
+ list<Predicate> Predicates = [HasVFP2];
+}
+
// Load / store multiple
class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 198974afe2..1a4a8847d9 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -129,23 +129,17 @@ def nModImm : Operand<i32> {
// NEON load / store instructions
//===----------------------------------------------------------------------===//
-// Use vldmia to load a Q register as a D register pair.
-// This is equivalent to VLDMD except that it has a Q register operand
-// instead of a pair of D registers.
+// Use VLDM to load a Q register as a D register pair.
+// This is a pseudo instruction that is expanded to VLDMD after reg alloc.
def VLDMQ
- : AXDI4<(outs QPR:$dst), (ins addrmode4:$addr, pred:$p),
- IndexModeNone, IIC_fpLoadm,
- "vldm${addr:submode}${p}\t$addr, ${dst:dregpair}", "",
- [(set QPR:$dst, (v2f64 (load addrmode4:$addr)))]>;
-
-// Use vstmia to store a Q register as a D register pair.
-// This is equivalent to VSTMD except that it has a Q register operand
-// instead of a pair of D registers.
+ : PseudoVFPLdStM<(outs QPR:$dst), (ins addrmode4:$addr), IIC_fpLoadm, "",
+ [(set QPR:$dst, (v2f64 (load addrmode4:$addr)))]>;
+
+// Use VSTM to store a Q register as a D register pair.
+// This is a pseudo instruction that is expanded to VSTMD after reg alloc.
def VSTMQ
- : AXDI4<(outs), (ins QPR:$src, addrmode4:$addr, pred:$p),
- IndexModeNone, IIC_fpStorem,
- "vstm${addr:submode}${p}\t$addr, ${src:dregpair}", "",
- [(store (v2f64 QPR:$src), addrmode4:$addr)]>;
+ : PseudoVFPLdStM<(outs), (ins QPR:$src, addrmode4:$addr), IIC_fpStorem, "",
+ [(store (v2f64 QPR:$src), addrmode4:$addr)]>;
let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {