diff options
Diffstat (limited to 'lib/CodeGen/LivePhysRegs.cpp')
| -rw-r--r-- | lib/CodeGen/LivePhysRegs.cpp | 114 | 
1 files changed, 114 insertions, 0 deletions
| diff --git a/lib/CodeGen/LivePhysRegs.cpp b/lib/CodeGen/LivePhysRegs.cpp new file mode 100644 index 000000000000..7efd941322b3 --- /dev/null +++ b/lib/CodeGen/LivePhysRegs.cpp @@ -0,0 +1,114 @@ +//===--- LivePhysRegs.cpp - Live Physical Register Set --------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LivePhysRegs utility for tracking liveness of +// physical registers across machine instructions in forward or backward order. +// A more detailed description can be found in the corresponding header file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + + +/// \brief Remove all registers from the set that get clobbered by the register +/// mask. +void LivePhysRegs::removeRegsInMask(const MachineOperand &MO) { +  SparseSet<unsigned>::iterator LRI = LiveRegs.begin(); +  while (LRI != LiveRegs.end()) { +    if (MO.clobbersPhysReg(*LRI)) +      LRI = LiveRegs.erase(LRI); +    else +      ++LRI; +  } +} + +/// Simulates liveness when stepping backwards over an instruction(bundle): +/// Remove Defs, add uses. This is the recommended way of calculating liveness. +void LivePhysRegs::stepBackward(const MachineInstr &MI) { +  // Remove defined registers and regmask kills from the set. +  for (ConstMIBundleOperands O(&MI); O.isValid(); ++O) { +    if (O->isReg()) { +      if (!O->isDef()) +        continue; +      unsigned Reg = O->getReg(); +      if (Reg == 0) +        continue; +      removeReg(Reg); +    } else if (O->isRegMask()) +      removeRegsInMask(*O); +  } + +  // Add uses to the set. +  for (ConstMIBundleOperands O(&MI); O.isValid(); ++O) { +    if (!O->isReg() || !O->readsReg() || O->isUndef()) +      continue; +    unsigned Reg = O->getReg(); +    if (Reg == 0) +      continue; +    addReg(Reg); +  } +} + +/// Simulates liveness when stepping forward over an instruction(bundle): Remove +/// killed-uses, add defs. This is the not recommended way, because it depends +/// on accurate kill flags. If possible use stepBackwards() instead of this +/// function. +void LivePhysRegs::stepForward(const MachineInstr &MI) { +  SmallVector<unsigned, 4> Defs; +  // Remove killed registers from the set. +  for (ConstMIBundleOperands O(&MI); O.isValid(); ++O) { +    if (O->isReg()) { +      unsigned Reg = O->getReg(); +      if (Reg == 0) +        continue; +      if (O->isDef()) { +        if (!O->isDead()) +          Defs.push_back(Reg); +      } else { +        if (!O->isKill()) +          continue; +        assert(O->isUse()); +        removeReg(Reg); +      } +    } else if (O->isRegMask()) +      removeRegsInMask(*O); +  } + +  // Add defs to the set. +  for (unsigned i = 0, e = Defs.size(); i != e; ++i) +    addReg(Defs[i]); +} + +/// Prin the currently live registers to OS. +void LivePhysRegs::print(raw_ostream &OS) const { +  OS << "Live Registers:"; +  if (!TRI) { +    OS << " (uninitialized)\n"; +    return; +  } + +  if (empty()) { +    OS << " (empty)\n"; +    return; +  } + +  for (const_iterator I = begin(), E = end(); I != E; ++I) +    OS << " " << PrintReg(*I, TRI); +  OS << "\n"; +} + +/// Dumps the currently live registers to the debug output. +void LivePhysRegs::dump() const { +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +  dbgs() << "  " << *this; +#endif +} | 
