llvm-6502/lib/CodeGen/LivePhysRegs.cpp
Pete Cooper 2bce3aa5f1 Refactor UpdatePredRedefs and StepForward to avoid duplication. NFC
Note, this is a reapplication of r236515 with a fix to not assert on non-register operands, but instead only handle them until the subsequent commit.  Original commit message follows.

The code was basically the same here already.  Just added an out parameter for a vector of seen defs so that UpdatePredRedefs can call StepForward first, then do its own post processing on the seen defs.

Will be used in the next commit to also handle regmasks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236538 91177308-0d34-0410-b5e6-96231b3b80d8
2015-05-05 20:14:22 +00:00

121 lines
3.6 KiB
C++

//===--- 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"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
/// \brief Remove all registers from the set that get clobbered by the register
/// mask.
/// The clobbers set will be the list of live registers clobbered
/// by the regmask.
void LivePhysRegs::removeRegsInMask(const MachineOperand &MO,
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers) {
SparseSet<unsigned>::iterator LRI = LiveRegs.begin();
while (LRI != LiveRegs.end()) {
if (MO.clobbersPhysReg(*LRI)) {
if (Clobbers)
Clobbers->push_back(std::make_pair(*LRI, &MO));
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, nullptr);
}
// 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,
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> &Clobbers) {
// 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())
Clobbers.push_back(std::make_pair(Reg, &*O));
} else {
if (!O->isKill())
continue;
assert(O->isUse());
removeReg(Reg);
}
} else if (O->isRegMask())
removeRegsInMask(*O, &Clobbers);
}
// Add defs to the set.
for (auto Reg : Clobbers)
addReg(Reg.first);
}
/// 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
}