//===-- HexagonGlobalRegion.cpp - VLIW global scheduling infrastructure ---===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Basic infrastructure for global scheduling. Liveness update. // This is the least complete portion. Basically it is empty infrastructure // to be extended and improved. // Currently in place only trace region formation routines and non fully // functional skeleton for incremental liveness update. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "global_sched" #include "HexagonGlobalRegion.h" #include "HexagonTargetMachine.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; LivenessInfo::LivenessInfo(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, MachineBasicBlock *MBB) : TII(TII), TRI(TRI) { LiveIns.resize(TRI->getNumRegs()); LiveOuts.resize(TRI->getNumRegs()); LiveIns.reset(); LiveOuts.reset(); // Live-ins are simple, just copy from MBB. for (const auto &LI : MBB->liveins()) setUsed(LiveIns, LI.PhysReg); // Live-outs are concatenation of all the BB successors. // As of now, we are only dealing with a-cyclic regions // with side exits, but no side entrances. for (const MachineBasicBlock *Succ : MBB->successors()) for (const auto &LI : Succ->liveins()) setUsed(LiveOuts, LI.PhysReg); } // Pessimistically check if at least one def of this register in this // instruction (bundle or not) is done under predication. static bool isPredicatedDef(MachineInstr *MI, unsigned Reg, const HexagonInstrInfo *QII) { if (!MI->isBundle()) return QII->isPredicated(*MI); MachineBasicBlock *Parent = MI->getParent(); if (!Parent) return false; MachineBasicBlock::instr_iterator MII = MI->getIterator(); MachineBasicBlock::instr_iterator MIIE = Parent->instr_end(); for (++MII; MII != MIIE && MII->isInsideBundle(); ++MII) { if (!QII->isPredicated(*MII)) continue; for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MII->getOperand(i); if (!MO.isReg()) continue; if (MO.isDef() && !MO.isDead() && MO.getReg() == Reg) { LLVM_DEBUG(dbgs() << "\t\tCond def: "; MII->dump()); return true; } } } return false; } /// Determine def/use set for MI. /// Beware, if def is conditional, like here: /// BUNDLE %PC, %R0, %P0, %R16 /// * %R0 = LDriuh_cdnNotPt %P0, %R16, 0; /// * %P0 = C2_cmpeqi %R16, 0; /// It is not a statefull definition of R0. /// void LivenessInfo::parseOperands(MachineInstr *MI, BitVector &Gen, BitVector &Kill, BitVector &Use) { const auto *QII = static_cast(TII); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) continue; // If it is a predicated instruction, it may, or may not // be setting its destination, and we do not know it // at the compile time. if (MO.isDef() && !MO.isDead()) { if (isPredicatedDef(MI, MO.getReg(), QII)) LLVM_DEBUG(dbgs() << "\tConditional define of " << printReg(MO.getReg(), TRI) << " in "; MI->dump()); else setUsed(Gen, MO.getReg()); } if (MO.isKill()) setUsed(Kill, MO.getReg()); if (MO.isUse()) setUsed(Use, MO.getReg()); } } void LivenessInfo::parseOperandsWithReset(MachineInstr *MI, BitVector &Gen, BitVector &Kill, BitVector &Use) { Gen.reset(); Use.reset(); Kill.reset(); parseOperands(MI, Gen, Kill, Use); } /// setUsed - Set the register and its sub-registers as being used. /// Taken from RegScavenger::setUsed(). void LivenessInfo::setUsed(BitVector &Set, unsigned Reg) { Set.set(Reg); for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) Set.set(*SubRegs); } #ifndef NDEBUG static void dumpRI(const TargetRegisterInfo *TRI, BitVector &Set) { for (unsigned i = 0; i < Set.size(); i++) if (Set.test(i)) LLVM_DEBUG(dbgs() << " " << printReg(i, TRI)); } #endif // This function incrementally updates liveness for the given BB. // First it gathers LiveOut set, and then iterates bottom-up // over bundles/instructions while updating live set. void LivenessInfo::UpdateLiveness(MachineBasicBlock *MBB) { BitVector NewLiveIns(TRI->getNumRegs()); BitVector NewLiveOuts(TRI->getNumRegs()); BitVector LiveIns(TRI->getNumRegs()); BitVector LocalGen(TRI->getNumRegs()); BitVector LocalUse(TRI->getNumRegs()); BitVector LocalKill(TRI->getNumRegs()); NewLiveIns.reset(); NewLiveOuts.reset(); LLVM_DEBUG(dbgs() << "\n\t\tUpdateLiveness for BB(" << MBB->getNumber() << ")\n"); // Original Live-ins are simple, just copy from MBB. for (const auto &LI : MBB->liveins()) setUsed(NewLiveIns, LI.PhysReg); // Live-outs are concatenation of all the BB successors. // As of now, we are only dealing with a-cyclic regions // with side exits, but no side entrances. for (const MachineBasicBlock *Succ : MBB->successors()) for (const auto &LI : Succ->liveins()) setUsed(NewLiveOuts, LI.PhysReg); LiveIns = NewLiveIns; // This needs to be a sequential walk, not parallel update. LLVM_DEBUG(dbgs() << "\t\tOriginal live ins :\t"; dumpRI(TRI, NewLiveIns); dbgs() << "\n"); LLVM_DEBUG(dbgs() << "\t\tOriginal live outs:\t"; dumpRI(TRI, NewLiveOuts); dbgs() << "\n"); NewLiveIns = NewLiveOuts; // Scan BB backwards to get exposed uses. // TODO: Handle predicates if needed. std::vector BundleList; for (MachineBasicBlock::iterator MI = MBB->begin(), MIE = MBB->end(); MI != MIE; ++MI) if (!MI->isDebugInstr()) BundleList.push_back(&*MI); while (!BundleList.empty()) { MachineInstr *MI = BundleList.back(); BundleList.pop_back(); parseOperandsWithReset(MI, LocalGen, LocalKill, LocalUse); LLVM_DEBUG(dbgs() << "\t\tIncr gen:\t"; dumpRI(TRI, LocalGen); dbgs() << "\n"); LLVM_DEBUG(dbgs() << "\t\tIncr use:\t"; dumpRI(TRI, LocalUse); dbgs() << "\n"); // NewLiveIns = (NewLiveIns - LocalGen) U LocalUse. BitVector NotGen(LocalGen); NotGen.flip(); NewLiveIns &= NotGen; NewLiveIns |= LocalUse; } LLVM_DEBUG(dbgs() << "\t\tAnswer:\t"; dumpRI(TRI, NewLiveIns); dbgs() << "\n"); // TODO: Consider implementing a register aliasing filter if duplicate // live-in entries become problematic. // Set new live in. LLVM_DEBUG(dbgs() << "\t\tNew LiveIn :\t"); for (unsigned i = 0; i < LiveIns.size(); ++i) { if (NewLiveIns.test(i)) LLVM_DEBUG(dbgs() << " " << printReg(i, TRI)); if (LiveIns.test(i) == NewLiveIns.test(i)) continue; if (LiveIns.test(i)) MBB->removeLiveIn(i); if (NewLiveIns.test(i)) MBB->addLiveIn(i); } LLVM_DEBUG(dbgs() << "\n"); } void LivenessInfo::dump() { for (unsigned i = 0; i < LiveIns.size(); i++) if (LiveIns.test(i)) LLVM_DEBUG(dbgs() << "\t\tlive-in: " << printReg(i, TRI) << "\n"); for (unsigned i = 0; i < LiveOuts.size(); i++) if (LiveOuts.test(i)) LLVM_DEBUG(dbgs() << "\t\tlive-out: " << printReg(i, TRI) << "\n"); } /// /// BasicBlockRegion Methods. /// BasicBlockRegion::BasicBlockRegion(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, MachineBasicBlock *MBB) : TII(TII), TRI(TRI) { // Should be the root BB. Elements.push_back(MBB); ElementIndex[MBB] = 0; LiveInfo[MBB] = std::make_unique(TII, TRI, MBB); } BasicBlockRegion::~BasicBlockRegion() { LiveInfo.clear(); Elements.clear(); ElementIndex.clear(); } LivenessInfo *BasicBlockRegion::getLivenessInfoForBB(MachineBasicBlock *MBB) { auto It = LiveInfo.find(MBB); assert(It != LiveInfo.end() && "Missing Liveness info"); assert(It->second && "Missing Liveness info"); return It->second.get(); } void BasicBlockRegion::addBBtoRegion(MachineBasicBlock *MBB) { // It is OK to have duplicates if we reparse for additional BBs. if (LiveInfo.find(MBB) != LiveInfo.end()) return; ElementIndex[MBB] = static_cast(Elements.size()); Elements.push_back(MBB); LiveInfo[MBB] = std::make_unique(TII, TRI, MBB); }