bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, bool &sawLoad, bool &sawStore, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { if (candidate->isImplicitDef() || candidate->isKill()) return true; if (candidate->mayLoad()) { sawLoad = true; if (sawStore) return true; } if (candidate->mayStore()) { if (sawStore) return true; sawStore = true; if (sawLoad) return true; } for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) { const MachineOperand &MO = candidate->getOperand(i); if (!MO.isReg()) continue; // skip unsigned Reg = MO.getReg(); if (MO.isDef()) { // check whether Reg is defined or used before delay slot. if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg)) return true; } if (MO.isUse()) { // check whether Reg is defined before delay slot. if (IsRegInSet(RegDefs, Reg)) return true; } } unsigned Opcode = candidate->getOpcode(); // LD and LDD may have NOPs inserted afterwards in the case of some LEON // processors, so we can't use the delay slot if this feature is switched-on. if (Subtarget->insertNOPLoad() && Opcode >= SP::LDDArr && Opcode <= SP::LDrr) return true; // Same as above for FDIV and FSQRT on some LEON processors. if (Subtarget->fixAllFDIVSQRT() && Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD) return true; return false; }
bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, bool &sawLoad, bool &sawStore, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { if (candidate->isImplicitDef() || candidate->isKill()) return true; // Loads or stores cannot be moved past a store to the delay slot // and stores cannot be moved past a load. if (candidate->mayLoad()) { if (sawStore) return true; sawLoad = true; } if (candidate->mayStore()) { if (sawStore) return true; sawStore = true; if (sawLoad) return true; } assert((!candidate->isCall() && !candidate->isReturn()) && "Cannot put calls or returns in delay slot."); for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) { const MachineOperand &MO = candidate->getOperand(i); unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg())) continue; // skip if (MO.isDef()) { // check whether Reg is defined or used before delay slot. if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg)) return true; } if (MO.isUse()) { // check whether Reg is defined before delay slot. if (IsRegInSet(RegDefs, Reg)) return true; } } return false; }
bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, bool &sawLoad, bool &sawStore, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { if (candidate->isImplicitDef() || candidate->isKill()) return true; if (candidate->mayLoad()) { sawLoad = true; if (sawStore) return true; } if (candidate->mayStore()) { if (sawStore) return true; sawStore = true; if (sawLoad) return true; } for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) { const MachineOperand &MO = candidate->getOperand(i); if (!MO.isReg()) continue; // skip unsigned Reg = MO.getReg(); if (MO.isDef()) { //check whether Reg is defined or used before delay slot. if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg)) return true; } if (MO.isUse()) { //check whether Reg is defined before delay slot. if (IsRegInSet(RegDefs, Reg)) return true; } } return false; }
bool MSPUPacketizer::runOnMachineFunction(MachineFunction &Fn) { const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>(); // Instantiate the packetizer. MSPUPacketizerList Packetizer(Fn, MLI, MDT); // DFA state table should not be empty. assert(Packetizer.getResourceTracker() && "Empty DFA table!"); // // Loop over all basic blocks and remove KILL pseudo-instructions // These instructions confuse the dependence analysis. Consider: // D0 = ... (Insn 0) // R0 = KILL R0, D0 (Insn 1) // R0 = ... (Insn 2) // Here, Insn 1 will result in the dependence graph not emitting an output // dependence between Insn 0 and Insn 2. This can lead to incorrect // packetization // for(MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) { MachineBasicBlock::iterator End = MBB->end(); MachineBasicBlock::iterator MI = MBB->begin(); while(MI != End) { if(MI->isKill()) { MachineBasicBlock::iterator DeleteMI = MI; ++MI; MBB->erase(DeleteMI); End = MBB->end(); continue; } ++MI; } } // Loop over all of the basic blocks. for(MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) { // Find scheduling regions and schedule / packetize each region. unsigned RemainingCount = MBB->size(); for(MachineBasicBlock::iterator RegionEnd = MBB->end(); RegionEnd != MBB->begin();) { // The next region starts above the previous region. Look backward in the // instruction stream until we find the nearest boundary. MachineBasicBlock::iterator I = RegionEnd; for(; I != MBB->begin(); --I, --RemainingCount) { if(TII->isSchedulingBoundary(llvm::prior(I), MBB, Fn)) break; } I = MBB->begin(); // Skip empty scheduling regions. if(I == RegionEnd) { RegionEnd = llvm::prior(RegionEnd); --RemainingCount; continue; } // Skip regions with one instruction. if(I == llvm::prior(RegionEnd)) { RegionEnd = llvm::prior(RegionEnd); continue; } // PacketizeMIs() does a VLIW scheduling on MachineInstr list and packetizing. Packetizer.PacketizeMIs(MBB, I, RegionEnd); RegionEnd = I; } } return true; }