From 9cca551091d1727cbc83b0a5ee558ed689d07d27 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Tue, 7 Jan 2014 10:00:03 +0000 Subject: [AArch64]Add support to copy D tuples such as DPair/DTriple/DQuad and Q tuples such as QPair/QTriple/QQuad. There is no test case for D tuple as the original test cases are too large. As the copy of the D tuple is similar to the Q tuple, the correctness can be guaranteed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198682 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64InstrInfo.cpp | 52 ++++++++++++++++++++++++++++++++- lib/Target/AArch64/AArch64InstrInfo.h | 3 ++ 2 files changed, 54 insertions(+), 1 deletion(-) (limited to 'lib/Target/AArch64') diff --git a/lib/Target/AArch64/AArch64InstrInfo.cpp b/lib/Target/AArch64/AArch64InstrInfo.cpp index 1e19eb0c74..f4d13932a5 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -134,7 +134,8 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } } else { - llvm_unreachable("Unknown register class in copyPhysReg"); + CopyPhysRegTuple(MBB, I, DL, DestReg, SrcReg); + return; } // E.g. ORR xDst, xzr, xSrc, lsl #0 @@ -144,6 +145,55 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, .addImm(0); } +void AArch64InstrInfo::CopyPhysRegTuple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, + unsigned SrcReg) const { + unsigned SubRegs; + bool IsQRegs; + if (AArch64::DPairRegClass.contains(DestReg, SrcReg)) { + SubRegs = 2; + IsQRegs = false; + } else if (AArch64::DTripleRegClass.contains(DestReg, SrcReg)) { + SubRegs = 3; + IsQRegs = false; + } else if (AArch64::DQuadRegClass.contains(DestReg, SrcReg)) { + SubRegs = 4; + IsQRegs = false; + } else if (AArch64::QPairRegClass.contains(DestReg, SrcReg)) { + SubRegs = 2; + IsQRegs = true; + } else if (AArch64::QTripleRegClass.contains(DestReg, SrcReg)) { + SubRegs = 3; + IsQRegs = true; + } else if (AArch64::QQuadRegClass.contains(DestReg, SrcReg)) { + SubRegs = 4; + IsQRegs = true; + } else + llvm_unreachable("Unknown register class"); + + unsigned BeginIdx = IsQRegs ? AArch64::qsub_0 : AArch64::dsub_0; + int Spacing = 1; + const TargetRegisterInfo *TRI = &getRegisterInfo(); + // Copy register tuples backward when the first Dest reg overlaps + // with SrcReg. + if (TRI->regsOverlap(SrcReg, TRI->getSubReg(DestReg, BeginIdx))) { + BeginIdx = BeginIdx + (SubRegs - 1); + Spacing = -1; + } + + unsigned Opc = IsQRegs ? AArch64::ORRvvv_16B : AArch64::ORRvvv_8B; + for (unsigned i = 0; i != SubRegs; ++i) { + unsigned Dst = TRI->getSubReg(DestReg, BeginIdx + i * Spacing); + unsigned Src = TRI->getSubReg(SrcReg, BeginIdx + i * Spacing); + assert(Dst && Src && "Bad sub-register"); + BuildMI(MBB, I, I->getDebugLoc(), get(Opc), Dst) + .addReg(Src) + .addReg(Src); + } + return; +} + /// Does the Opcode represent a conditional branch that we can remove and re-add /// at the end of a basic block? static bool isCondBranch(unsigned Opc) { diff --git a/lib/Target/AArch64/AArch64InstrInfo.h b/lib/Target/AArch64/AArch64InstrInfo.h index 620ecc93b1..946e5da5cf 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.h +++ b/lib/Target/AArch64/AArch64InstrInfo.h @@ -42,6 +42,9 @@ public: MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const; + void CopyPhysRegTuple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg) const; void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, -- cgit v1.2.3