From c8141dfc7f983cb04e65d8acd6bcbdc8e4b8a0ae Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 26 Oct 2010 02:08:50 +0000 Subject: [PATCH] Use instruction itinerary to determine what instructions are 'cheap'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117348 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetInstrInfo.h | 6 ++++ lib/CodeGen/MachineLICM.cpp | 40 ++++++++++++++++++++++++--- lib/Target/ARM/ARMBaseInstrInfo.cpp | 15 ++++++++++ lib/Target/ARM/ARMBaseInstrInfo.h | 2 ++ lib/Target/TargetInstrInfo.cpp | 10 +++++++ 5 files changed, 69 insertions(+), 4 deletions(-) diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 936345c5046..0ecfc79c6b9 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -639,6 +639,12 @@ public: const MachineInstr *UseMI, unsigned UseIdx) const { return false; } + + /// hasLowDefLatency - Compute operand latency of a def of 'Reg', return true + /// if the target considered it 'low'. + virtual + bool hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const; }; /// TargetInstrInfoImpl - This is the default implementation of diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 3f060ccc4ea..2308ee6010f 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -173,7 +173,10 @@ namespace { /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. - bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx, unsigned Reg); + bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx, + unsigned Reg) const; + + bool IsCheapInstruction(MachineInstr &MI) const; /// CanCauseHighRegPressure - Visit BBs from header to current BB, /// check if hoisting an instruction of the given cost matrix can cause high @@ -795,13 +798,15 @@ bool MachineLICM::isLoadFromConstantMemory(MachineInstr *MI) { /// and an use in the current loop, return true if the target considered /// it 'high'. bool MachineLICM::HasHighOperandLatency(MachineInstr &MI, - unsigned DefIdx, unsigned Reg) { - if (MRI->use_nodbg_empty(Reg)) + unsigned DefIdx, unsigned Reg) const { + if (!InstrItins || InstrItins->isEmpty() || MRI->use_nodbg_empty(Reg)) return false; for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg), E = MRI->use_nodbg_end(); I != E; ++I) { MachineInstr *UseMI = &*I; + if (UseMI->isCopyLike()) + continue; if (!CurLoop->contains(UseMI->getParent())) continue; for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) { @@ -823,6 +828,33 @@ bool MachineLICM::HasHighOperandLatency(MachineInstr &MI, return false; } +/// IsCheapInstruction - Return true if the instruction is marked "cheap" or +/// the operand latency between its def and a use is one or less. +bool MachineLICM::IsCheapInstruction(MachineInstr &MI) const { + if (MI.getDesc().isAsCheapAsAMove() || MI.isCopyLike()) + return true; + if (!InstrItins || InstrItins->isEmpty()) + return false; + + bool isCheap = false; + unsigned NumDefs = MI.getDesc().getNumDefs(); + for (unsigned i = 0, e = MI.getNumOperands(); NumDefs && i != e; ++i) { + MachineOperand &DefMO = MI.getOperand(i); + if (!DefMO.isReg() || !DefMO.isDef()) + continue; + --NumDefs; + unsigned Reg = DefMO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + + if (!TII->hasLowDefLatency(InstrItins, &MI, i)) + return false; + isCheap = true; + } + + return isCheap; +} + /// CanCauseHighRegPressure - Visit BBs from header to current BB, check /// if hoisting an instruction of the given cost matrix can cause high /// register pressure. @@ -905,7 +937,7 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { // trade off is it may cause spill in high pressure situation. It will end up // adding a store in the loop preheader. But the reload is no more expensive. // The side benefit is these loads are frequently CSE'ed. - if (MI.getDesc().isAsCheapAsAMove()) { + if (IsCheapInstruction(MI)) { if (!TII->isTriviallyReMaterializable(&MI, AA)) return false; } else { diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 757ca13512c..8834ff3268f 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1951,3 +1951,18 @@ hasHighOperandLatency(const InstrItineraryData *ItinData, return DDomain == ARMII::DomainVFP || DDomain == ARMII::DomainNEON || UDomain == ARMII::DomainVFP || UDomain == ARMII::DomainNEON; } + +bool ARMBaseInstrInfo:: +hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const { + if (!ItinData || ItinData->isEmpty()) + return false; + + unsigned DDomain = DefMI->getDesc().TSFlags & ARMII::DomainMask; + if (DDomain == ARMII::DomainGeneral) { + unsigned DefClass = DefMI->getDesc().getSchedClass(); + int DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); + return (DefCycle != -1 && DefCycle <= 2); + } + return false; +} diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index b665fd5ecb0..f607f267c68 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -382,6 +382,8 @@ private: const MachineRegisterInfo *MRI, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const; + bool hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const; }; static inline diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index 7f103226daf..62818d0cae9 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -94,6 +94,16 @@ TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx); } +bool TargetInstrInfo::hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, + unsigned DefIdx) const { + if (!ItinData || ItinData->isEmpty()) + return false; + + unsigned DefClass = DefMI->getDesc().getSchedClass(); + int DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); + return (DefCycle != -1 && DefCycle <= 1); +} /// insertNoop - Insert a noop into the instruction stream at the specified /// point.