void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap, RegToRangeMap &LiveMap) { std::map<RegisterRef,IndexType> LastDef, LastUse; RegisterSet LiveOnEntry; MachineBasicBlock &B = IndexMap.getBlock(); MachineRegisterInfo &MRI = B.getParent()->getRegInfo(); for (auto R : getLiveIns(B, MRI, TRI)) LiveOnEntry.insert(R); for (auto R : LiveOnEntry) LastDef[R] = IndexType::Entry; auto closeRange = [&LastUse,&LastDef,&LiveMap] (RegisterRef R) -> void { auto LD = LastDef[R], LU = LastUse[R]; if (LD == IndexType::None) LD = IndexType::Entry; if (LU == IndexType::None) LU = IndexType::Exit; LiveMap[R].add(LD, LU, false, false); LastUse[R] = LastDef[R] = IndexType::None; }; RegisterSet Defs, Clobbers; for (auto &In : B) { if (In.isDebugInstr()) continue; IndexType Index = IndexMap.getIndex(&In); // Process uses first. for (auto &Op : In.operands()) { if (!Op.isReg() || !Op.isUse() || Op.isUndef()) continue; RegisterRef R = { Op.getReg(), Op.getSubReg() }; if (TargetRegisterInfo::isPhysicalRegister(R.Reg) && Reserved[R.Reg]) continue; bool IsKill = Op.isKill(); for (auto S : expandToSubRegs(R, MRI, TRI)) { LastUse[S] = Index; if (IsKill) closeRange(S); } } // Process defs and clobbers. Defs.clear(); Clobbers.clear(); for (auto &Op : In.operands()) { if (!Op.isReg() || !Op.isDef() || Op.isUndef()) continue; RegisterRef R = { Op.getReg(), Op.getSubReg() }; for (auto S : expandToSubRegs(R, MRI, TRI)) { if (TargetRegisterInfo::isPhysicalRegister(S.Reg) && Reserved[S.Reg]) continue; if (Op.isDead()) Clobbers.insert(S); else Defs.insert(S); } } for (auto &Op : In.operands()) { if (!Op.isRegMask()) continue; const uint32_t *BM = Op.getRegMask(); for (unsigned PR = 1, N = TRI.getNumRegs(); PR != N; ++PR) { // Skip registers that have subregisters. A register is preserved // iff its bit is set in the regmask, so if R1:0 was preserved, both // R1 and R0 would also be present. if (MCSubRegIterator(PR, &TRI, false).isValid()) continue; if (Reserved[PR]) continue; if (BM[PR/32] & (1u << (PR%32))) continue; RegisterRef R = { PR, 0 }; if (!Defs.count(R)) Clobbers.insert(R); } } // Defs and clobbers can overlap, e.g. // dead %d0 = COPY %5, implicit-def %r0, implicit-def %r1 for (RegisterRef R : Defs) Clobbers.erase(R); // Update maps for defs. for (RegisterRef S : Defs) { // Defs should already be expanded into subregs. assert(!TargetRegisterInfo::isPhysicalRegister(S.Reg) || !MCSubRegIterator(S.Reg, &TRI, false).isValid()); if (LastDef[S] != IndexType::None || LastUse[S] != IndexType::None) closeRange(S); LastDef[S] = Index; } // Update maps for clobbers. for (RegisterRef S : Clobbers) { // Clobbers should already be expanded into subregs. assert(!TargetRegisterInfo::isPhysicalRegister(S.Reg) || !MCSubRegIterator(S.Reg, &TRI, false).isValid()); if (LastDef[S] != IndexType::None || LastUse[S] != IndexType::None) closeRange(S); // Create a single-instruction range. LastDef[S] = LastUse[S] = Index; closeRange(S); } } // Collect live-on-exit. RegisterSet LiveOnExit; for (auto *SB : B.successors()) for (auto R : getLiveIns(*SB, MRI, TRI)) LiveOnExit.insert(R); for (auto R : LiveOnExit) LastUse[R] = IndexType::Exit; // Process remaining registers. RegisterSet Left; for (auto &I : LastUse) if (I.second != IndexType::None) Left.insert(I.first); for (auto &I : LastDef) if (I.second != IndexType::None) Left.insert(I.first); for (auto R : Left) closeRange(R); // Finalize the live ranges. for (auto &P : LiveMap) P.second.unionize(); }
void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap, RegToRangeMap &LiveMap) { std::map<RegisterRef,IndexType> LastDef, LastUse; RegisterSet LiveOnEntry; MachineBasicBlock &B = IndexMap.getBlock(); MachineRegisterInfo &MRI = B.getParent()->getRegInfo(); for (auto R : getLiveIns(B)) for (auto S : expandToSubRegs(R, MRI, TRI)) LiveOnEntry.insert(S); for (auto R : LiveOnEntry) LastDef[R] = IndexType::Entry; auto closeRange = [&LastUse,&LastDef,&LiveMap] (RegisterRef R) -> void { auto LD = LastDef[R], LU = LastUse[R]; if (LD == IndexType::None) LD = IndexType::Entry; if (LU == IndexType::None) LU = IndexType::Exit; LiveMap[R].add(LD, LU, false, false); LastUse[R] = LastDef[R] = IndexType::None; }; for (auto &In : B) { if (In.isDebugValue()) continue; IndexType Index = IndexMap.getIndex(&In); // Process uses first. for (auto &Op : In.operands()) { if (!Op.isReg() || !Op.isUse() || Op.isUndef()) continue; RegisterRef R = { Op.getReg(), Op.getSubReg() }; if (TargetRegisterInfo::isPhysicalRegister(R.Reg) && Reserved[R.Reg]) continue; bool IsKill = Op.isKill(); for (auto S : expandToSubRegs(R, MRI, TRI)) { LastUse[S] = Index; if (IsKill) closeRange(S); } } // Process defs. for (auto &Op : In.operands()) { if (!Op.isReg() || !Op.isDef() || Op.isUndef()) continue; RegisterRef R = { Op.getReg(), Op.getSubReg() }; if (TargetRegisterInfo::isPhysicalRegister(R.Reg) && Reserved[R.Reg]) continue; for (auto S : expandToSubRegs(R, MRI, TRI)) { if (LastDef[S] != IndexType::None || LastUse[S] != IndexType::None) closeRange(S); LastDef[S] = Index; } } } // Collect live-on-exit. RegisterSet LiveOnExit; for (auto *SB : B.successors()) for (auto R : getLiveIns(*SB)) for (auto S : expandToSubRegs(R, MRI, TRI)) LiveOnExit.insert(S); for (auto R : LiveOnExit) LastUse[R] = IndexType::Exit; // Process remaining registers. RegisterSet Left; for (auto &I : LastUse) if (I.second != IndexType::None) Left.insert(I.first); for (auto &I : LastDef) if (I.second != IndexType::None) Left.insert(I.first); for (auto R : Left) closeRange(R); // Finalize the live ranges. for (auto &P : LiveMap) P.second.unionize(); }