| //===-- 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<imp-def>, %R0<imp-def>, %P0<imp-use,kill>, %R16<imp-use> |
| /// * %R0<def> = LDriuh_cdnNotPt %P0<kill,internal>, %R16, 0; |
| /// * %P0<def> = 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<const HexagonInstrInfo *>(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<MachineInstr *> 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<LivenessInfo>(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<unsigned>(Elements.size()); |
| Elements.push_back(MBB); |
| LiveInfo[MBB] = std::make_unique<LivenessInfo>(TII, TRI, MBB); |
| } |