static bool hasRegisterDependency(MachineInstr *MI, SmallVectorImpl<unsigned> &UsedOpsInCopy, SmallVectorImpl<unsigned> &DefedRegsInCopy, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits) { bool HasRegDependency = false; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!Reg) continue; if (MO.isDef()) { if (!ModifiedRegUnits.available(Reg) || !UsedRegUnits.available(Reg)) { HasRegDependency = true; break; } DefedRegsInCopy.push_back(Reg); // FIXME: instead of isUse(), readsReg() would be a better fix here, // For example, we can ignore modifications in reg with undef. However, // it's not perfectly clear if skipping the internal read is safe in all // other targets. } else if (MO.isUse()) { if (!ModifiedRegUnits.available(Reg)) { HasRegDependency = true; break; } UsedOpsInCopy.push_back(i); } } return HasRegDependency; }
static void clearKillFlags(MachineInstr *MI, MachineBasicBlock &CurBB, SmallVectorImpl<unsigned> &UsedOpsInCopy, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI) { for (auto U : UsedOpsInCopy) { MachineOperand &MO = MI->getOperand(U); unsigned SrcReg = MO.getReg(); if (!UsedRegUnits.available(SrcReg)) { MachineBasicBlock::iterator NI = std::next(MI->getIterator()); for (MachineInstr &UI : make_range(NI, CurBB.end())) { if (UI.killsRegister(SrcReg, TRI)) { UI.clearRegisterKills(SrcReg, TRI); MO.setIsKill(true); break; } } } } }
/// Given the bitvector \p Available of free register units at position /// \p From. Search backwards to find a register that is part of \p /// Candidates and not used/clobbered until the point \p To. If there is /// multiple candidates continue searching and pick the one that is not used/ /// clobbered for the longest time. /// Returns the register and the earliest position we know it to be free or /// the position MBB.end() if no register is available. static std::pair<MCPhysReg, MachineBasicBlock::iterator> findSurvivorBackwards(const MachineRegisterInfo &MRI, MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const LiveRegUnits &LiveOut, ArrayRef<MCPhysReg> AllocationOrder) { bool FoundTo = false; MCPhysReg Survivor = 0; MachineBasicBlock::iterator Pos; MachineBasicBlock &MBB = *From->getParent(); unsigned InstrLimit = 25; unsigned InstrCountDown = InstrLimit; const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); LiveRegUnits Used(TRI); for (MachineBasicBlock::iterator I = From;; --I) { const MachineInstr &MI = *I; Used.accumulateBackward(MI); if (I == To) { // See if one of the registers in RC wasn't used so far. for (MCPhysReg Reg : AllocationOrder) { if (!MRI.isReserved(Reg) && Used.available(Reg) && LiveOut.available(Reg)) return std::make_pair(Reg, MBB.end()); } // Otherwise we will continue up to InstrLimit instructions to find // the register which is not defined/used for the longest time. FoundTo = true; Pos = To; } if (FoundTo) { if (Survivor == 0 || !Used.available(Survivor)) { MCPhysReg AvilableReg = 0; for (MCPhysReg Reg : AllocationOrder) { if (!MRI.isReserved(Reg) && Used.available(Reg)) { AvilableReg = Reg; break; } } if (AvilableReg == 0) break; Survivor = AvilableReg; } if (--InstrCountDown == 0) break; // Keep searching when we find a vreg since the spilled register will // be usefull for this other vreg as well later. bool FoundVReg = false; for (const MachineOperand &MO : MI.operands()) { if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())) { FoundVReg = true; break; } } if (FoundVReg) { InstrCountDown = InstrLimit; Pos = I; } if (I == MBB.begin()) break; } } return std::make_pair(Survivor, Pos); }