From 13fd601e0f1c6d8558c4c2b027dacd148f19e6af Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 27 Sep 2011 22:57:21 +0000 Subject: [PATCH] Implement TII::get/setExecutionDomain() for ARM. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140653 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseInstrInfo.cpp | 53 +++++++++++++++++++++++++++++ lib/Target/ARM/ARMBaseInstrInfo.h | 6 ++++ 2 files changed, 59 insertions(+) diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 1c36cd08f66..70ac487e4bf 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -2720,3 +2720,56 @@ ARMBaseInstrInfo::isFpMLxInstruction(unsigned Opcode, unsigned &MulOpc, HasLane = Entry.HasLane; return true; } + +//===----------------------------------------------------------------------===// +// Execution domains. +//===----------------------------------------------------------------------===// +// +// Some instructions go down the NEON pipeline, some go down the VFP pipeline, +// and some can go down both. The vmov instructions go down the VFP pipeline, +// but they can be changed to vorr equivalents that are executed by the NEON +// pipeline. +// +// We use the following execution domain numbering: +// +// 0: Generic +// 1: VFP +// 2: NEON +// +// Also see ARMInstrFormats.td and Domain* enums in ARMBaseInfo.h +// +std::pair +ARMBaseInstrInfo::getExecutionDomain(const MachineInstr *MI) const { + // VMOVD is a VFP instruction, but can be changed to NEON if it isn't + // predicated. + if (MI->getOpcode() == ARM::VMOVD && !isPredicated(MI)) + return std::make_pair(1, 3); + + // No other instructions can be swizzled, so just determine their domain. + unsigned Domain = MI->getDesc().TSFlags & ARMII::DomainMask; + + if (Domain & ARMII::DomainNEON) + return std::make_pair(2, 0); + + // Certain instructions can go either way on Cortex-A8. + // Treat them as NEON instructions. + if ((Domain & ARMII::DomainNEONA8) && Subtarget.isCortexA8()) + return std::make_pair(2, 0); + + if (Domain & ARMII::DomainVFP) + return std::make_pair(1, 0); + + return std::make_pair(0, 0); +} + +void +ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const { + // We only know how to change VMOVD into VORR. + assert(MI->getOpcode() == ARM::VMOVD && "Can only swizzle VMOVD"); + if (Domain != 2) + return; + + // Change to a VORRd which requires two identical use operands. + MI->setDesc(get(ARM::VORRd)); + MachineInstrBuilder(MI).addReg(MI->getOperand(1).getReg()); +} diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 8ba64d03073..30dd6973fda 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -210,6 +210,12 @@ public: int getOperandLatency(const InstrItineraryData *ItinData, SDNode *DefNode, unsigned DefIdx, SDNode *UseNode, unsigned UseIdx) const; + + /// VFP/NEON execution domains. + std::pair + getExecutionDomain(const MachineInstr *MI) const; + void setExecutionDomain(MachineInstr *MI, unsigned Domain) const; + private: int getVLDMDefCycle(const InstrItineraryData *ItinData, const MCInstrDesc &DefMCID,