diff options
author | Vincent Lejeune <vljn@ovi.com> | 2013-09-04 19:53:46 +0000 |
---|---|---|
committer | Vincent Lejeune <vljn@ovi.com> | 2013-09-04 19:53:46 +0000 |
commit | bb25a01d232257b134f1f6a5810116cbb04b95b1 (patch) | |
tree | c8372c60ee26e9325086cf932b4a20633f3f9487 /lib/Target/R600 | |
parent | b3df27d4402d8c8fc81d5acec812035360806cdc (diff) | |
download | external_llvm-bb25a01d232257b134f1f6a5810116cbb04b95b1.zip external_llvm-bb25a01d232257b134f1f6a5810116cbb04b95b1.tar.gz external_llvm-bb25a01d232257b134f1f6a5810116cbb04b95b1.tar.bz2 |
R600: Non vector only instruction can be scheduled on trans unit
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189980 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/R600')
-rw-r--r-- | lib/Target/R600/R600InstrInfo.cpp | 3 | ||||
-rw-r--r-- | lib/Target/R600/R600MachineScheduler.cpp | 33 | ||||
-rw-r--r-- | lib/Target/R600/R600MachineScheduler.h | 5 | ||||
-rw-r--r-- | lib/Target/R600/R600Packetizer.cpp | 38 |
4 files changed, 60 insertions, 19 deletions
diff --git a/lib/Target/R600/R600InstrInfo.cpp b/lib/Target/R600/R600InstrInfo.cpp index 212463f..e3cb71b 100644 --- a/lib/Target/R600/R600InstrInfo.cpp +++ b/lib/Target/R600/R600InstrInfo.cpp @@ -477,6 +477,9 @@ static bool isConstCompatible(R600InstrInfo::BankSwizzle TransSwz, const std::vector<std::pair<int, unsigned> > &TransOps, unsigned ConstCount) { + // TransALU can't read 3 constants + if (ConstCount > 2) + return false; for (unsigned i = 0, e = TransOps.size(); i < e; ++i) { const std::pair<int, unsigned> &Src = TransOps[i]; unsigned Cycle = getTransSwizzle(TransSwz, i); diff --git a/lib/Target/R600/R600MachineScheduler.cpp b/lib/Target/R600/R600MachineScheduler.cpp index 0dc0365..0499dd5 100644 --- a/lib/Target/R600/R600MachineScheduler.cpp +++ b/lib/Target/R600/R600MachineScheduler.cpp @@ -9,7 +9,6 @@ // /// \file /// \brief R600 Machine Scheduler interface -// TODO: Scheduling is optimised for VLIW4 arch, modify it to support TRANS slot // //===----------------------------------------------------------------------===// @@ -29,6 +28,7 @@ void R600SchedStrategy::initialize(ScheduleDAGMI *dag) { DAG = dag; TII = static_cast<const R600InstrInfo*>(DAG->TII); TRI = static_cast<const R600RegisterInfo*>(DAG->TRI); + VLIW5 = !DAG->MF.getTarget().getSubtarget<AMDGPUSubtarget>().hasCaymanISA(); MRI = &DAG->MRI; CurInstKind = IDOther; CurEmitted = 0; @@ -342,14 +342,16 @@ int R600SchedStrategy::getInstKind(SUnit* SU) { } } -SUnit *R600SchedStrategy::PopInst(std::vector<SUnit *> &Q) { +SUnit *R600SchedStrategy::PopInst(std::vector<SUnit *> &Q, bool AnyALU) { if (Q.empty()) return NULL; for (std::vector<SUnit *>::reverse_iterator It = Q.rbegin(), E = Q.rend(); It != E; ++It) { SUnit *SU = *It; InstructionsGroupCandidate.push_back(SU->getInstr()); - if (TII->fitsConstReadLimitations(InstructionsGroupCandidate)) { + if (TII->fitsConstReadLimitations(InstructionsGroupCandidate) + && (!AnyALU || !TII->isVectorOnly(SU->getInstr())) + ) { InstructionsGroupCandidate.pop_back(); Q.erase((It + 1).base()); return SU; @@ -373,6 +375,8 @@ void R600SchedStrategy::PrepareNextSlot() { DEBUG(dbgs() << "New Slot\n"); assert (OccupedSlotsMask && "Slot wasn't filled"); OccupedSlotsMask = 0; +// if (HwGen == AMDGPUSubtarget::NORTHERN_ISLANDS) +// OccupedSlotsMask |= 16; InstructionsGroupCandidate.clear(); LoadAlu(); } @@ -409,12 +413,12 @@ void R600SchedStrategy::AssignSlot(MachineInstr* MI, unsigned Slot) { } } -SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot) { +SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot, bool AnyAlu) { static const AluKind IndexToID[] = {AluT_X, AluT_Y, AluT_Z, AluT_W}; - SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]]); + SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]], AnyAlu); if (SlotedSU) return SlotedSU; - SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny]); + SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny], AnyAlu); if (UnslotedSU) AssignSlot(UnslotedSU->getInstr(), Slot); return UnslotedSU; @@ -434,30 +438,35 @@ SUnit* R600SchedStrategy::pickAlu() { // Bottom up scheduling : predX must comes first if (!AvailableAlus[AluPredX].empty()) { OccupedSlotsMask |= 31; - return PopInst(AvailableAlus[AluPredX]); + return PopInst(AvailableAlus[AluPredX], false); } // Flush physical reg copies (RA will discard them) if (!AvailableAlus[AluDiscarded].empty()) { OccupedSlotsMask |= 31; - return PopInst(AvailableAlus[AluDiscarded]); + return PopInst(AvailableAlus[AluDiscarded], false); } // If there is a T_XYZW alu available, use it if (!AvailableAlus[AluT_XYZW].empty()) { OccupedSlotsMask |= 15; - return PopInst(AvailableAlus[AluT_XYZW]); + return PopInst(AvailableAlus[AluT_XYZW], false); } } bool TransSlotOccuped = OccupedSlotsMask & 16; - if (!TransSlotOccuped) { + if (!TransSlotOccuped && VLIW5) { if (!AvailableAlus[AluTrans].empty()) { OccupedSlotsMask |= 16; - return PopInst(AvailableAlus[AluTrans]); + return PopInst(AvailableAlus[AluTrans], false); + } + SUnit *SU = AttemptFillSlot(3, true); + if (SU) { + OccupedSlotsMask |= 16; + return SU; } } for (int Chan = 3; Chan > -1; --Chan) { bool isOccupied = OccupedSlotsMask & (1 << Chan); if (!isOccupied) { - SUnit *SU = AttemptFillSlot(Chan); + SUnit *SU = AttemptFillSlot(Chan, false); if (SU) { OccupedSlotsMask |= (1 << Chan); InstructionsGroupCandidate.push_back(SU->getInstr()); diff --git a/lib/Target/R600/R600MachineScheduler.h b/lib/Target/R600/R600MachineScheduler.h index f8965d8..0a6f120 100644 --- a/lib/Target/R600/R600MachineScheduler.h +++ b/lib/Target/R600/R600MachineScheduler.h @@ -84,15 +84,16 @@ public: private: std::vector<MachineInstr *> InstructionsGroupCandidate; + bool VLIW5; int getInstKind(SUnit *SU); bool regBelongsToClass(unsigned Reg, const TargetRegisterClass *RC) const; AluKind getAluKind(SUnit *SU) const; void LoadAlu(); unsigned AvailablesAluCount() const; - SUnit *AttemptFillSlot (unsigned Slot); + SUnit *AttemptFillSlot (unsigned Slot, bool AnyAlu); void PrepareNextSlot(); - SUnit *PopInst(std::vector<SUnit*> &Q); + SUnit *PopInst(std::vector<SUnit*> &Q, bool AnyALU); void AssignSlot(MachineInstr *MI, unsigned Slot); SUnit* pickAlu(); diff --git a/lib/Target/R600/R600Packetizer.cpp b/lib/Target/R600/R600Packetizer.cpp index 5cf1fd3..6c70052 100644 --- a/lib/Target/R600/R600Packetizer.cpp +++ b/lib/Target/R600/R600Packetizer.cpp @@ -58,6 +58,8 @@ class R600PacketizerList : public VLIWPacketizerList { private: const R600InstrInfo *TII; const R600RegisterInfo &TRI; + bool VLIW5; + bool ConsideredInstUsesAlreadyWrittenVectorElement; unsigned getSlot(const MachineInstr *MI) const { return TRI.getHWRegChan(MI->getOperand(0).getReg()); @@ -74,7 +76,13 @@ private: MachineBasicBlock::instr_iterator BI = I.getInstrIterator(); if (I->isBundle()) BI++; + int LastDstChan = -1; do { + bool isTrans = false; + int BISlot = getSlot(BI); + if (LastDstChan >= BISlot) + isTrans = true; + LastDstChan = BISlot; if (TII->isPredicated(BI)) continue; int OperandIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::write); @@ -85,7 +93,7 @@ private: continue; } unsigned Dst = BI->getOperand(DstIdx).getReg(); - if (TII->isTransOnly(BI)) { + if (isTrans || TII->isTransOnly(BI)) { Result[Dst] = AMDGPU::PS; continue; } @@ -142,10 +150,14 @@ public: MachineDominatorTree &MDT) : VLIWPacketizerList(MF, MLI, MDT, true), TII (static_cast<const R600InstrInfo *>(MF.getTarget().getInstrInfo())), - TRI(TII->getRegisterInfo()) { } + TRI(TII->getRegisterInfo()) { + VLIW5 = !MF.getTarget().getSubtarget<AMDGPUSubtarget>().hasCaymanISA(); + } // initPacketizerState - initialize some internal flags. - void initPacketizerState() { } + void initPacketizerState() { + ConsideredInstUsesAlreadyWrittenVectorElement = false; + } // ignorePseudoInstruction - Ignore bundling of pseudo instructions. bool ignorePseudoInstruction(MachineInstr *MI, MachineBasicBlock *MBB) { @@ -172,8 +184,8 @@ public: // together. bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr(); - if (getSlot(MII) <= getSlot(MIJ) && !TII->isTransOnly(MII)) - return false; + if (getSlot(MII) == getSlot(MIJ)) + ConsideredInstUsesAlreadyWrittenVectorElement = true; // Does MII and MIJ share the same pred_sel ? int OpI = TII->getOperandIdx(MII->getOpcode(), AMDGPU::OpName::pred_sel), OpJ = TII->getOperandIdx(MIJ->getOpcode(), AMDGPU::OpName::pred_sel); @@ -211,6 +223,20 @@ public: std::vector<R600InstrInfo::BankSwizzle> &BS, bool &isTransSlot) { isTransSlot = TII->isTransOnly(MI); + assert (!isTransSlot || VLIW5); + + // Is the dst reg sequence legal ? + if (!isTransSlot && !CurrentPacketMIs.empty()) { + if (getSlot(MI) <= getSlot(CurrentPacketMIs.back())) { + if (ConsideredInstUsesAlreadyWrittenVectorElement && + !TII->isVectorOnly(MI) && VLIW5) { + isTransSlot = true; + DEBUG(dbgs() << "Considering as Trans Inst :"; MI->dump();); + } + else + return false; + } + } // Are the Constants limitations met ? CurrentPacketMIs.push_back(MI); @@ -278,6 +304,8 @@ public: return It; } endPacket(MI->getParent(), MI); + if (TII->isTransOnly(MI)) + return MI; return VLIWPacketizerList::addToPacket(MI); } }; |