[llvm-commits] [parallel] CVS: llvm/lib/CodeGen/MachineBasicBlock.cpp PhysRegTracker.h VirtRegMap.cpp VirtRegMap.h LiveIntervals.cpp LiveIntervals.h LiveVariables.cpp MachineCodeEmitter.cpp MachineCodeForInstruction.cpp MachineFunction.cpp MachineInstr.cpp MachineInstrAnnot.cpp PHIElimination.cpp Passes.cpp PrologEpilogInserter.cpp RegAllocLinearScan.cpp RegAllocLocal.cpp RegAllocSimple.cpp TwoAddressInstructionPass.cpp
Misha Brukman
brukman at cs.uiuc.edu
Mon Mar 1 18:06:33 PST 2004
Changes in directory llvm/lib/CodeGen:
MachineBasicBlock.cpp added (r1.9.2.1)
PhysRegTracker.h added (r1.4.2.1)
VirtRegMap.cpp added (r1.8.2.1)
VirtRegMap.h added (r1.9.2.1)
LiveIntervals.cpp updated: 1.28 -> 1.28.2.1
LiveIntervals.h updated: 1.11 -> 1.11.2.1
LiveVariables.cpp updated: 1.15 -> 1.15.2.1
MachineCodeEmitter.cpp updated: 1.14 -> 1.14.4.1
MachineCodeForInstruction.cpp updated: 1.11 -> 1.11.2.1
MachineFunction.cpp updated: 1.46 -> 1.46.2.1
MachineInstr.cpp updated: 1.82 -> 1.82.2.1
MachineInstrAnnot.cpp updated: 1.10 -> 1.10.4.1
PHIElimination.cpp updated: 1.14 -> 1.14.2.1
Passes.cpp updated: 1.5 -> 1.5.2.1
PrologEpilogInserter.cpp updated: 1.16 -> 1.16.2.1
RegAllocLinearScan.cpp updated: 1.31 -> 1.31.2.1
RegAllocLocal.cpp updated: 1.37 -> 1.37.2.1
RegAllocSimple.cpp updated: 1.47 -> 1.47.2.1
TwoAddressInstructionPass.cpp updated: 1.6 -> 1.6.2.1
---
Log message:
Merge from trunk
---
Diffs of the changes: (+2022 -1250)
Index: llvm/lib/CodeGen/MachineBasicBlock.cpp
diff -c /dev/null llvm/lib/CodeGen/MachineBasicBlock.cpp:1.9.2.1
*** /dev/null Mon Mar 1 17:58:27 2004
--- llvm/lib/CodeGen/MachineBasicBlock.cpp Mon Mar 1 17:58:13 2004
***************
*** 0 ****
--- 1,83 ----
+ //===-- llvm/CodeGen/MachineBasicBlock.cpp ----------------------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // Collect the sequence of machine instructions for a basic block.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "llvm/CodeGen/MachineBasicBlock.h"
+ #include "llvm/BasicBlock.h"
+ #include "llvm/CodeGen/MachineFunction.h"
+ #include "llvm/CodeGen/MachineInstr.h"
+ #include "llvm/Target/TargetInstrInfo.h"
+ #include "llvm/Target/TargetMachine.h"
+ #include "Support/LeakDetector.h"
+ using namespace llvm;
+
+ const MachineFunction *MachineBasicBlock::getParent() const {
+ // Get the parent by getting the Function parent of the basic block, and
+ // getting the MachineFunction from it.
+ return &MachineFunction::get(getBasicBlock()->getParent());
+ }
+
+
+ MachineInstr* ilist_traits<MachineInstr>::createNode()
+ {
+ MachineInstr* dummy = new MachineInstr(0, 0);
+ LeakDetector::removeGarbageObject(dummy);
+ return dummy;
+ }
+
+ void ilist_traits<MachineInstr>::addNodeToList(MachineInstr* N)
+ {
+ assert(N->parent == 0 && "machine instruction already in a basic block");
+ N->parent = parent;
+ LeakDetector::removeGarbageObject(N);
+ }
+
+ void ilist_traits<MachineInstr>::removeNodeFromList(MachineInstr* N)
+ {
+ assert(N->parent != 0 && "machine instruction not in a basic block");
+ N->parent = 0;
+ LeakDetector::addGarbageObject(N);
+ }
+
+ void ilist_traits<MachineInstr>::transferNodesFromList(
+ iplist<MachineInstr, ilist_traits<MachineInstr> >& toList,
+ ilist_iterator<MachineInstr> first,
+ ilist_iterator<MachineInstr> last)
+ {
+ if (parent != toList.parent)
+ for (; first != last; ++first)
+ first->parent = toList.parent;
+ }
+
+ MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator()
+ {
+ const TargetInstrInfo& TII = getParent()->getTarget().getInstrInfo();
+ iterator I = end();
+ while (I != begin() && TII.isTerminatorInstr((--I)->getOpcode()));
+ if (I != end() && !TII.isTerminatorInstr(I->getOpcode())) ++I;
+ return I;
+ }
+
+ void MachineBasicBlock::dump() const
+ {
+ print(std::cerr);
+ }
+
+ void MachineBasicBlock::print(std::ostream &OS) const
+ {
+ const BasicBlock *LBB = getBasicBlock();
+ OS << "\n" << LBB->getName() << " (" << (const void*)LBB << "):\n";
+ for (const_iterator I = begin(); I != end(); ++I) {
+ OS << "\t";
+ I->print(OS, MachineFunction::get(LBB->getParent()).getTarget());
+ }
+ }
Index: llvm/lib/CodeGen/PhysRegTracker.h
diff -c /dev/null llvm/lib/CodeGen/PhysRegTracker.h:1.4.2.1
*** /dev/null Mon Mar 1 17:58:27 2004
--- llvm/lib/CodeGen/PhysRegTracker.h Mon Mar 1 17:58:13 2004
***************
*** 0 ****
--- 1,73 ----
+ //===-- llvm/CodeGen/PhysRegTracker.h - Physical Register Tracker -*- C++ -*-=//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements a physical register tracker. The tracker
+ // tracks physical register usage through addRegUse and
+ // delRegUse. isRegAvail checks if a physical register is available or
+ // not taking into consideration register aliases.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef LLVM_CODEGEN_PHYSREGTRACKER_H
+ #define LLVM_CODEGEN_PHYSREGTRACKER_H
+
+ #include "llvm/Target/MRegisterInfo.h"
+
+ namespace llvm {
+
+ class PhysRegTracker {
+ const MRegisterInfo* mri_;
+ std::vector<unsigned> regUse_;
+
+ public:
+ PhysRegTracker(const MRegisterInfo& mri)
+ : mri_(&mri),
+ regUse_(mri_->getNumRegs(), 0) {
+ }
+
+ PhysRegTracker(const PhysRegTracker& rhs)
+ : mri_(rhs.mri_),
+ regUse_(rhs.regUse_) {
+ }
+
+ const PhysRegTracker& operator=(const PhysRegTracker& rhs) {
+ mri_ = rhs.mri_;
+ regUse_ = rhs.regUse_;
+ return *this;
+ }
+
+ void addRegUse(unsigned physReg) {
+ assert(MRegisterInfo::isPhysicalRegister(physReg) &&
+ "should be physical register!");
+ ++regUse_[physReg];
+ for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as)
+ ++regUse_[*as];
+ }
+
+ void delRegUse(unsigned physReg) {
+ assert(MRegisterInfo::isPhysicalRegister(physReg) &&
+ "should be physical register!");
+ assert(regUse_[physReg] != 0);
+ --regUse_[physReg];
+ for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
+ assert(regUse_[*as] != 0);
+ --regUse_[*as];
+ }
+ }
+
+ bool isRegAvail(unsigned physReg) const {
+ assert(MRegisterInfo::isPhysicalRegister(physReg) &&
+ "should be physical register!");
+ return regUse_[physReg] == 0;
+ }
+ };
+
+ } // End llvm namespace
+
+ #endif
Index: llvm/lib/CodeGen/VirtRegMap.cpp
diff -c /dev/null llvm/lib/CodeGen/VirtRegMap.cpp:1.8.2.1
*** /dev/null Mon Mar 1 17:58:28 2004
--- llvm/lib/CodeGen/VirtRegMap.cpp Mon Mar 1 17:58:13 2004
***************
*** 0 ****
--- 1,285 ----
+ //===-- llvm/CodeGen/VirtRegMap.cpp - Virtual Register Map ----------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements the virtual register map. It also implements
+ // the eliminateVirtRegs() function that given a virtual register map
+ // and a machine function it eliminates all virtual references by
+ // replacing them with physical register references and adds spill
+ // code as necessary.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #define DEBUG_TYPE "regalloc"
+ #include "VirtRegMap.h"
+ #include "llvm/Function.h"
+ #include "llvm/CodeGen/MachineFrameInfo.h"
+ #include "llvm/CodeGen/MachineInstr.h"
+ #include "llvm/Target/TargetMachine.h"
+ #include "llvm/Target/TargetInstrInfo.h"
+ #include "Support/CommandLine.h"
+ #include "Support/Debug.h"
+ #include "Support/DenseMap.h"
+ #include "Support/Statistic.h"
+ #include "Support/STLExtras.h"
+ #include <iostream>
+
+ using namespace llvm;
+
+ namespace {
+ Statistic<> numSpills("spiller", "Number of register spills");
+ Statistic<> numStores("spiller", "Number of stores added");
+ Statistic<> numLoads ("spiller", "Number of loads added");
+
+ enum SpillerName { local };
+
+ cl::opt<SpillerName>
+ SpillerOpt("spiller",
+ cl::desc("Spiller to use: (default: local)"),
+ cl::Prefix,
+ cl::values(clEnumVal(local, " local spiller"),
+ 0),
+ cl::init(local));
+ }
+
+ int VirtRegMap::assignVirt2StackSlot(unsigned virtReg)
+ {
+ assert(MRegisterInfo::isVirtualRegister(virtReg));
+ assert(v2ssMap_[virtReg] == NO_STACK_SLOT &&
+ "attempt to assign stack slot to already spilled register");
+ const TargetRegisterClass* rc =
+ mf_->getSSARegMap()->getRegClass(virtReg);
+ int frameIndex = mf_->getFrameInfo()->CreateStackObject(rc);
+ v2ssMap_[virtReg] = frameIndex;
+ ++numSpills;
+ return frameIndex;
+ }
+
+ void VirtRegMap::virtFolded(unsigned virtReg,
+ MachineInstr* oldMI,
+ MachineInstr* newMI)
+ {
+ // move previous memory references folded to new instruction
+ MI2VirtMap::iterator i, e;
+ std::vector<MI2VirtMap::mapped_type> regs;
+ for (tie(i, e) = mi2vMap_.equal_range(oldMI); i != e; ) {
+ regs.push_back(i->second);
+ mi2vMap_.erase(i++);
+ }
+ for (unsigned i = 0, e = regs.size(); i != e; ++i)
+ mi2vMap_.insert(std::make_pair(newMI, i));
+
+ // add new memory reference
+ mi2vMap_.insert(std::make_pair(newMI, virtReg));
+ }
+
+ std::ostream& llvm::operator<<(std::ostream& os, const VirtRegMap& vrm)
+ {
+ const MRegisterInfo* mri = vrm.mf_->getTarget().getRegisterInfo();
+
+ std::cerr << "********** REGISTER MAP **********\n";
+ for (unsigned i = MRegisterInfo::FirstVirtualRegister,
+ e = vrm.mf_->getSSARegMap()->getLastVirtReg(); i <= e; ++i) {
+ if (vrm.v2pMap_[i] != VirtRegMap::NO_PHYS_REG)
+ std::cerr << "[reg" << i << " -> "
+ << mri->getName(vrm.v2pMap_[i]) << "]\n";
+ }
+ for (unsigned i = MRegisterInfo::FirstVirtualRegister,
+ e = vrm.mf_->getSSARegMap()->getLastVirtReg(); i <= e; ++i) {
+ if (vrm.v2ssMap_[i] != VirtRegMap::NO_STACK_SLOT)
+ std::cerr << "[reg" << i << " -> fi#"
+ << vrm.v2ssMap_[i] << "]\n";
+ }
+ return std::cerr << '\n';
+ }
+
+ Spiller::~Spiller()
+ {
+
+ }
+
+ namespace {
+
+ class LocalSpiller : public Spiller {
+ typedef std::vector<unsigned> Phys2VirtMap;
+ typedef std::vector<bool> PhysFlag;
+ typedef DenseMap<MachineInstr*, VirtReg2IndexFunctor> Virt2MI;
+
+ MachineFunction* mf_;
+ const TargetMachine* tm_;
+ const TargetInstrInfo* tii_;
+ const MRegisterInfo* mri_;
+ const VirtRegMap* vrm_;
+ Phys2VirtMap p2vMap_;
+ PhysFlag dirty_;
+ Virt2MI lastDef_;
+
+ public:
+ bool runOnMachineFunction(MachineFunction& mf, const VirtRegMap& vrm) {
+ mf_ = &mf;
+ tm_ = &mf_->getTarget();
+ tii_ = &tm_->getInstrInfo();
+ mri_ = tm_->getRegisterInfo();
+ vrm_ = &vrm;
+ p2vMap_.assign(mri_->getNumRegs(), 0);
+ dirty_.assign(mri_->getNumRegs(), false);
+
+ DEBUG(std::cerr << "********** REWRITE MACHINE CODE **********\n");
+ DEBUG(std::cerr << "********** Function: "
+ << mf_->getFunction()->getName() << '\n');
+
+ for (MachineFunction::iterator mbbi = mf_->begin(),
+ mbbe = mf_->end(); mbbi != mbbe; ++mbbi) {
+ lastDef_.grow(mf_->getSSARegMap()->getLastVirtReg());
+ DEBUG(std::cerr << mbbi->getBasicBlock()->getName() << ":\n");
+ eliminateVirtRegsInMbb(*mbbi);
+ // clear map, dirty flag and last ref
+ p2vMap_.assign(p2vMap_.size(), 0);
+ dirty_.assign(dirty_.size(), false);
+ lastDef_.clear();
+ }
+ return true;
+ }
+
+ private:
+ void vacateJustPhysReg(MachineBasicBlock& mbb,
+ MachineBasicBlock::iterator mii,
+ unsigned physReg) {
+ unsigned virtReg = p2vMap_[physReg];
+ if (dirty_[physReg] && vrm_->hasStackSlot(virtReg)) {
+ assert(lastDef_[virtReg] && "virtual register is mapped "
+ "to a register and but was not defined!");
+ MachineBasicBlock::iterator lastDef = lastDef_[virtReg];
+ MachineBasicBlock::iterator nextLastRef = next(lastDef);
+ mri_->storeRegToStackSlot(*lastDef->getParent(),
+ nextLastRef,
+ physReg,
+ vrm_->getStackSlot(virtReg),
+ mri_->getRegClass(physReg));
+ ++numStores;
+ DEBUG(std::cerr << "added: ";
+ prior(nextLastRef)->print(std::cerr, *tm_);
+ std::cerr << "after: ";
+ lastDef->print(std::cerr, *tm_));
+ lastDef_[virtReg] = 0;
+ }
+ p2vMap_[physReg] = 0;
+ dirty_[physReg] = false;
+ }
+
+ void vacatePhysReg(MachineBasicBlock& mbb,
+ MachineBasicBlock::iterator mii,
+ unsigned physReg) {
+ vacateJustPhysReg(mbb, mii, physReg);
+ for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as)
+ vacateJustPhysReg(mbb, mii, *as);
+ }
+
+ void handleUse(MachineBasicBlock& mbb,
+ MachineBasicBlock::iterator mii,
+ unsigned virtReg,
+ unsigned physReg) {
+ // check if we are replacing a previous mapping
+ if (p2vMap_[physReg] != virtReg) {
+ vacatePhysReg(mbb, mii, physReg);
+ p2vMap_[physReg] = virtReg;
+ // load if necessary
+ if (vrm_->hasStackSlot(virtReg)) {
+ mri_->loadRegFromStackSlot(mbb, mii, physReg,
+ vrm_->getStackSlot(virtReg),
+ mri_->getRegClass(physReg));
+ ++numLoads;
+ DEBUG(std::cerr << "added: ";
+ prior(mii)->print(std::cerr, *tm_));
+ lastDef_[virtReg] = mii;
+ }
+ }
+ }
+
+ void handleDef(MachineBasicBlock& mbb,
+ MachineBasicBlock::iterator mii,
+ unsigned virtReg,
+ unsigned physReg) {
+ // check if we are replacing a previous mapping
+ if (p2vMap_[physReg] != virtReg)
+ vacatePhysReg(mbb, mii, physReg);
+
+ p2vMap_[physReg] = virtReg;
+ dirty_[physReg] = true;
+ lastDef_[virtReg] = mii;
+ }
+
+ void eliminateVirtRegsInMbb(MachineBasicBlock& mbb) {
+ for (MachineBasicBlock::iterator mii = mbb.begin(),
+ mie = mbb.end(); mii != mie; ++mii) {
+
+ // if we have references to memory operands make sure
+ // we clear all physical registers that may contain
+ // the value of the spilled virtual register
+ VirtRegMap::MI2VirtMap::const_iterator i, e;
+ for (tie(i, e) = vrm_->getFoldedVirts(mii); i != e; ++i) {
+ unsigned physReg = vrm_->getPhys(i->second);
+ if (physReg) vacateJustPhysReg(mbb, mii, physReg);
+ }
+
+ // rewrite all used operands
+ for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
+ MachineOperand& op = mii->getOperand(i);
+ if (op.isRegister() && op.getReg() && op.isUse() &&
+ MRegisterInfo::isVirtualRegister(op.getReg())) {
+ unsigned virtReg = op.getReg();
+ unsigned physReg = vrm_->getPhys(virtReg);
+ handleUse(mbb, mii, virtReg, physReg);
+ mii->SetMachineOperandReg(i, physReg);
+ // mark as dirty if this is def&use
+ if (op.isDef()) {
+ dirty_[physReg] = true;
+ lastDef_[virtReg] = mii;
+ }
+ }
+ }
+
+ // spill implicit defs
+ const TargetInstrDescriptor& tid = tii_->get(mii->getOpcode());
+ for (const unsigned* id = tid.ImplicitDefs; *id; ++id)
+ vacatePhysReg(mbb, mii, *id);
+
+ // rewrite def operands (def&use was handled with the
+ // uses so don't check for those here)
+ for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
+ MachineOperand& op = mii->getOperand(i);
+ if (op.isRegister() && op.getReg() && !op.isUse())
+ if (MRegisterInfo::isPhysicalRegister(op.getReg()))
+ vacatePhysReg(mbb, mii, op.getReg());
+ else {
+ unsigned physReg = vrm_->getPhys(op.getReg());
+ handleDef(mbb, mii, op.getReg(), physReg);
+ mii->SetMachineOperandReg(i, physReg);
+ }
+ }
+
+ DEBUG(std::cerr << '\t'; mii->print(std::cerr, *tm_));
+ }
+
+ for (unsigned i = 1, e = p2vMap_.size(); i != e; ++i)
+ vacateJustPhysReg(mbb, mbb.getFirstTerminator(), i);
+
+ }
+ };
+ }
+
+ llvm::Spiller* llvm::createSpiller()
+ {
+ switch (SpillerOpt) {
+ default:
+ std::cerr << "no spiller selected";
+ abort();
+ case local:
+ return new LocalSpiller();
+ }
+ }
Index: llvm/lib/CodeGen/VirtRegMap.h
diff -c /dev/null llvm/lib/CodeGen/VirtRegMap.h:1.9.2.1
*** /dev/null Mon Mar 1 17:58:28 2004
--- llvm/lib/CodeGen/VirtRegMap.h Mon Mar 1 17:58:13 2004
***************
*** 0 ****
--- 1,122 ----
+ //===-- llvm/CodeGen/VirtRegMap.h - Virtual Register Map -*- C++ -*--------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements a virtual register map. This maps virtual
+ // registers to physical registers and virtual registers to stack
+ // slots. It is created and updated by a register allocator and then
+ // used by a machine code rewriter that adds spill code and rewrites
+ // virtual into physical register references.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef LLVM_CODEGEN_VIRTREGMAP_H
+ #define LLVM_CODEGEN_VIRTREGMAP_H
+
+ #include "llvm/CodeGen/MachineFunction.h"
+ #include "llvm/CodeGen/SSARegMap.h"
+ #include "Support/DenseMap.h"
+ #include <climits>
+ #include <map>
+
+ namespace llvm {
+
+ class MachineInstr;
+
+ class VirtRegMap {
+ public:
+ typedef DenseMap<unsigned, VirtReg2IndexFunctor> Virt2PhysMap;
+ typedef DenseMap<int, VirtReg2IndexFunctor> Virt2StackSlotMap;
+ typedef std::multimap<MachineInstr*, unsigned> MI2VirtMap;
+
+ private:
+ MachineFunction* mf_;
+ Virt2PhysMap v2pMap_;
+ Virt2StackSlotMap v2ssMap_;
+ MI2VirtMap mi2vMap_;
+
+ // do not implement
+ VirtRegMap(const VirtRegMap& rhs);
+ const VirtRegMap& operator=(const VirtRegMap& rhs);
+
+ enum {
+ NO_PHYS_REG = 0,
+ NO_STACK_SLOT = INT_MAX
+ };
+
+ public:
+ VirtRegMap(MachineFunction& mf)
+ : mf_(&mf),
+ v2pMap_(NO_PHYS_REG),
+ v2ssMap_(NO_STACK_SLOT) {
+ v2pMap_.grow(mf.getSSARegMap()->getLastVirtReg());
+ v2ssMap_.grow(mf.getSSARegMap()->getLastVirtReg());
+ }
+
+ bool hasPhys(unsigned virtReg) const {
+ return getPhys(virtReg) != NO_PHYS_REG;
+ }
+
+ unsigned getPhys(unsigned virtReg) const {
+ assert(MRegisterInfo::isVirtualRegister(virtReg));
+ return v2pMap_[virtReg];
+ }
+
+ void assignVirt2Phys(unsigned virtReg, unsigned physReg) {
+ assert(MRegisterInfo::isVirtualRegister(virtReg) &&
+ MRegisterInfo::isPhysicalRegister(physReg));
+ assert(v2pMap_[virtReg] == NO_PHYS_REG &&
+ "attempt to assign physical register to already mapped "
+ "virtual register");
+ v2pMap_[virtReg] = physReg;
+ }
+
+ void clearVirt(unsigned virtReg) {
+ assert(MRegisterInfo::isVirtualRegister(virtReg));
+ assert(v2pMap_[virtReg] != NO_PHYS_REG &&
+ "attempt to clear a not assigned virtual register");
+ v2pMap_[virtReg] = NO_PHYS_REG;
+ }
+
+ bool hasStackSlot(unsigned virtReg) const {
+ return getStackSlot(virtReg) != NO_STACK_SLOT;
+ }
+
+ int getStackSlot(unsigned virtReg) const {
+ assert(MRegisterInfo::isVirtualRegister(virtReg));
+ return v2ssMap_[virtReg];
+ }
+
+ int assignVirt2StackSlot(unsigned virtReg);
+
+ void virtFolded(unsigned virtReg,
+ MachineInstr* oldMI,
+ MachineInstr* newMI);
+
+ std::pair<MI2VirtMap::const_iterator, MI2VirtMap::const_iterator>
+ getFoldedVirts(MachineInstr* MI) const {
+ return mi2vMap_.equal_range(MI);
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const VirtRegMap& li);
+ };
+
+ std::ostream& operator<<(std::ostream& os, const VirtRegMap& li);
+
+ struct Spiller {
+ virtual ~Spiller();
+
+ virtual bool runOnMachineFunction(MachineFunction& mf, const VirtRegMap& vrm) = 0;
+
+ };
+
+ Spiller* createSpiller();
+
+ } // End llvm namespace
+
+ #endif
Index: llvm/lib/CodeGen/LiveIntervals.cpp
diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.28 llvm/lib/CodeGen/LiveIntervals.cpp:1.28.2.1
--- llvm/lib/CodeGen/LiveIntervals.cpp:1.28 Fri Jan 16 10:23:23 2004
+++ llvm/lib/CodeGen/LiveIntervals.cpp Mon Mar 1 17:58:13 2004
@@ -16,23 +16,22 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "liveintervals"
-#include "llvm/CodeGen/LiveIntervals.h"
-#include "llvm/Function.h"
+#include "LiveIntervals.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegInfo.h"
#include "llvm/Support/CFG.h"
+#include "Support/CommandLine.h"
#include "Support/Debug.h"
-#include "Support/DepthFirstIterator.h"
#include "Support/Statistic.h"
+#include "Support/STLExtras.h"
+#include "VirtRegMap.h"
#include <cmath>
#include <iostream>
#include <limits>
@@ -43,7 +42,25 @@
RegisterAnalysis<LiveIntervals> X("liveintervals",
"Live Interval Analysis");
- Statistic<> numIntervals("liveintervals", "Number of intervals");
+ Statistic<> numIntervals
+ ("liveintervals", "Number of original intervals");
+
+ Statistic<> numIntervalsAfter
+ ("liveintervals", "Number of intervals after coalescing");
+
+ Statistic<> numJoins
+ ("liveintervals", "Number of interval joins performed");
+
+ Statistic<> numPeep
+ ("liveintervals", "Number of identity moves eliminated after coalescing");
+
+ Statistic<> numFolded
+ ("liveintervals", "Number of loads/stores folded into instructions");
+
+ cl::opt<bool>
+ join("join-liveintervals",
+ cl::desc("Join compatible live intervals"),
+ cl::init(true));
};
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const
@@ -57,128 +74,241 @@
MachineFunctionPass::getAnalysisUsage(AU);
}
+void LiveIntervals::releaseMemory()
+{
+ mbbi2mbbMap_.clear();
+ mi2iMap_.clear();
+ i2miMap_.clear();
+ r2iMap_.clear();
+ r2rMap_.clear();
+ intervals_.clear();
+}
+
+
/// runOnMachineFunction - Register allocate the whole function
///
bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
- DEBUG(std::cerr << "Machine Function\n");
mf_ = &fn;
tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo();
lv_ = &getAnalysis<LiveVariables>();
- mbbi2mbbMap_.clear();
- mi2iMap_.clear();
- r2iMap_.clear();
- r2iMap_.clear();
- intervals_.clear();
// number MachineInstrs
unsigned miIndex = 0;
for (MachineFunction::iterator mbb = mf_->begin(), mbbEnd = mf_->end();
mbb != mbbEnd; ++mbb) {
const std::pair<MachineBasicBlock*, unsigned>& entry =
- lv_->getMachineBasicBlockInfo(&*mbb);
+ lv_->getMachineBasicBlockInfo(mbb);
bool inserted = mbbi2mbbMap_.insert(std::make_pair(entry.second,
entry.first)).second;
assert(inserted && "multiple index -> MachineBasicBlock");
for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end();
mi != miEnd; ++mi) {
- inserted = mi2iMap_.insert(std::make_pair(*mi, miIndex)).second;
+ inserted = mi2iMap_.insert(std::make_pair(mi, miIndex)).second;
assert(inserted && "multiple MachineInstr -> index mappings");
- ++miIndex;
+ i2miMap_.push_back(mi);
+ miIndex += InstrSlots::NUM;
}
}
computeIntervals();
- // compute spill weights
+ numIntervals += intervals_.size();
+
+ // join intervals if requested
+ if (join) joinIntervals();
+
+ numIntervalsAfter += intervals_.size();
+
+ // perform a final pass over the instructions and compute spill
+ // weights, coalesce virtual registers and remove identity moves
const LoopInfo& loopInfo = getAnalysis<LoopInfo>();
const TargetInstrInfo& tii = tm_->getInstrInfo();
- for (MbbIndex2MbbMap::iterator
- it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end();
- it != itEnd; ++it) {
- MachineBasicBlock* mbb = it->second;
-
+ for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
+ mbbi != mbbe; ++mbbi) {
+ MachineBasicBlock* mbb = mbbi;
unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock());
- for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end();
- mi != miEnd; ++mi) {
- MachineInstr* instr = *mi;
- for (int i = instr->getNumOperands() - 1; i >= 0; --i) {
- MachineOperand& mop = instr->getOperand(i);
-
- if (!mop.isVirtualRegister())
- continue;
+ for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end();
+ mii != mie; ) {
+ for (unsigned i = 0; i < mii->getNumOperands(); ++i) {
+ const MachineOperand& mop = mii->getOperand(i);
+ if (mop.isRegister() && mop.getReg()) {
+ // replace register with representative register
+ unsigned reg = rep(mop.getReg());
+ mii->SetMachineOperandReg(i, reg);
+
+ if (MRegisterInfo::isVirtualRegister(reg)) {
+ Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg);
+ assert(r2iit != r2iMap_.end());
+ r2iit->second->weight += pow(10.0F, loopDepth);
+ }
+ }
+ }
- unsigned reg = mop.getAllocatedRegNum();
- Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg);
- assert(r2iit != r2iMap_.end());
- r2iit->second->weight += pow(10.0F, loopDepth);
+ // if the move is now an identity move delete it
+ unsigned srcReg, dstReg;
+ if (tii.isMoveInstr(*mii, srcReg, dstReg) && srcReg == dstReg) {
+ // remove index -> MachineInstr and
+ // MachineInstr -> index mappings
+ Mi2IndexMap::iterator mi2i = mi2iMap_.find(mii);
+ if (mi2i != mi2iMap_.end()) {
+ i2miMap_[mi2i->second/InstrSlots::NUM] = 0;
+ mi2iMap_.erase(mi2i);
+ }
+ mii = mbbi->erase(mii);
+ ++numPeep;
}
+ else
+ ++mii;
}
}
- numIntervals += intervals_.size();
+ intervals_.sort(StartPointComp());
+ DEBUG(std::cerr << "********** INTERVALS **********\n");
+ DEBUG(std::copy(intervals_.begin(), intervals_.end(),
+ std::ostream_iterator<Interval>(std::cerr, "\n")));
+ DEBUG(std::cerr << "********** MACHINEINSTRS **********\n");
+ DEBUG(
+ for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
+ mbbi != mbbe; ++mbbi) {
+ std::cerr << mbbi->getBasicBlock()->getName() << ":\n";
+ for (MachineBasicBlock::iterator mii = mbbi->begin(),
+ mie = mbbi->end(); mii != mie; ++mii) {
+ std::cerr << getInstructionIndex(mii) << '\t';
+ mii->print(std::cerr, *tm_);
+ }
+ });
return true;
}
+void LiveIntervals::updateSpilledInterval(Interval& li,
+ VirtRegMap& vrm,
+ int slot)
+{
+ assert(li.weight != std::numeric_limits<float>::infinity() &&
+ "attempt to spill already spilled interval!");
+ Interval::Ranges oldRanges;
+ swap(oldRanges, li.ranges);
+
+ DEBUG(std::cerr << "\t\t\t\tupdating interval: " << li);
+
+ for (Interval::Ranges::iterator i = oldRanges.begin(), e = oldRanges.end();
+ i != e; ++i) {
+ unsigned index = getBaseIndex(i->first);
+ unsigned end = getBaseIndex(i->second-1) + InstrSlots::NUM;
+ for (; index < end; index += InstrSlots::NUM) {
+ // skip deleted instructions
+ while (!getInstructionFromIndex(index)) index += InstrSlots::NUM;
+ MachineBasicBlock::iterator mi = getInstructionFromIndex(index);
+
+ for_operand:
+ for (unsigned i = 0; i < mi->getNumOperands(); ++i) {
+ MachineOperand& mop = mi->getOperand(i);
+ if (mop.isRegister() && mop.getReg() == li.reg) {
+ MachineInstr* old = mi;
+ if (mri_->foldMemoryOperand(mi, i, slot)) {
+ lv_->instructionChanged(old, mi);
+ vrm.virtFolded(li.reg, old, mi);
+ mi2iMap_.erase(old);
+ i2miMap_[index/InstrSlots::NUM] = mi;
+ mi2iMap_[mi] = index;
+ ++numFolded;
+ goto for_operand;
+ }
+ else {
+ // This is tricky. We need to add information in
+ // the interval about the spill code so we have to
+ // use our extra load/store slots.
+ //
+ // If we have a use we are going to have a load so
+ // we start the interval from the load slot
+ // onwards. Otherwise we start from the def slot.
+ unsigned start = (mop.isUse() ?
+ getLoadIndex(index) :
+ getDefIndex(index));
+ // If we have a def we are going to have a store
+ // right after it so we end the interval after the
+ // use of the next instruction. Otherwise we end
+ // after the use of this instruction.
+ unsigned end = 1 + (mop.isDef() ?
+ getUseIndex(index+InstrSlots::NUM) :
+ getUseIndex(index));
+ li.addRange(start, end);
+ }
+ }
+ }
+ }
+ }
+ // the new spill weight is now infinity as it cannot be spilled again
+ li.weight = std::numeric_limits<float>::infinity();
+ DEBUG(std::cerr << '\n');
+ DEBUG(std::cerr << "\t\t\t\tupdated interval: " << li << '\n');
+}
+
void LiveIntervals::printRegName(unsigned reg) const
{
- if (reg < MRegisterInfo::FirstVirtualRegister)
+ if (MRegisterInfo::isPhysicalRegister(reg))
std::cerr << mri_->getName(reg);
else
- std::cerr << '%' << reg;
+ std::cerr << "%reg" << reg;
}
void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
MachineBasicBlock::iterator mi,
unsigned reg)
{
- DEBUG(std::cerr << "\t\tregister: ";printRegName(reg); std::cerr << '\n');
-
- unsigned instrIndex = getInstructionIndex(*mi);
-
+ DEBUG(std::cerr << "\t\tregister: "; printRegName(reg));
LiveVariables::VarInfo& vi = lv_->getVarInfo(reg);
Interval* interval = 0;
- Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg);
- if (r2iit == r2iMap_.end()) {
+ Reg2IntervalMap::iterator r2iit = r2iMap_.lower_bound(reg);
+ if (r2iit == r2iMap_.end() || r2iit->first != reg) {
// add new interval
intervals_.push_back(Interval(reg));
// update interval index for this register
- bool inserted =
- r2iMap_.insert(std::make_pair(reg, --intervals_.end())).second;
- assert(inserted);
+ r2iMap_.insert(r2iit, std::make_pair(reg, --intervals_.end()));
interval = &intervals_.back();
+
+ // iterate over all of the blocks that the variable is
+ // completely live in, adding them to the live
+ // interval. obviously we only need to do this once.
+ for (unsigned i = 0, e = vi.AliveBlocks.size(); i != e; ++i) {
+ if (vi.AliveBlocks[i]) {
+ MachineBasicBlock* mbb = lv_->getIndexMachineBasicBlock(i);
+ if (!mbb->empty()) {
+ interval->addRange(
+ getInstructionIndex(&mbb->front()),
+ getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
+ }
+ }
+ }
}
else {
interval = &*r2iit->second;
}
- for (MbbIndex2MbbMap::iterator
- it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end();
- it != itEnd; ++it) {
- unsigned liveBlockIndex = it->first;
- MachineBasicBlock* liveBlock = it->second;
- if (liveBlockIndex < vi.AliveBlocks.size() &&
- vi.AliveBlocks[liveBlockIndex] &&
- !liveBlock->empty()) {
- unsigned start = getInstructionIndex(liveBlock->front());
- unsigned end = getInstructionIndex(liveBlock->back()) + 1;
- interval->addRange(start, end);
- }
- }
+ unsigned baseIndex = getInstructionIndex(mi);
bool killedInDefiningBasicBlock = false;
for (int i = 0, e = vi.Kills.size(); i != e; ++i) {
MachineBasicBlock* killerBlock = vi.Kills[i].first;
MachineInstr* killerInstr = vi.Kills[i].second;
unsigned start = (mbb == killerBlock ?
- instrIndex :
- getInstructionIndex(killerBlock->front()));
- unsigned end = getInstructionIndex(killerInstr) + 1;
+ getDefIndex(baseIndex) :
+ getInstructionIndex(&killerBlock->front()));
+ unsigned end = (killerInstr == mi ?
+ // dead
+ start + 1 :
+ // killed
+ getUseIndex(getInstructionIndex(killerInstr))+1);
+ // we do not want to add invalid ranges. these can happen when
+ // a variable has its latest use and is redefined later on in
+ // the same basic block (common with variables introduced by
+ // PHI elimination)
if (start < end) {
killedInDefiningBasicBlock |= mbb == killerBlock;
interval->addRange(start, end);
@@ -186,9 +316,10 @@
}
if (!killedInDefiningBasicBlock) {
- unsigned end = getInstructionIndex(mbb->back()) + 1;
- interval->addRange(instrIndex, end);
+ unsigned end = getInstructionIndex(&mbb->back()) + InstrSlots::NUM;
+ interval->addRange(getDefIndex(baseIndex), end);
}
+ DEBUG(std::cerr << '\n');
}
void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock* mbb,
@@ -196,72 +327,58 @@
unsigned reg)
{
DEBUG(std::cerr << "\t\tregister: "; printRegName(reg));
+ typedef LiveVariables::killed_iterator KillIter;
- unsigned start = getInstructionIndex(*mi);
+ MachineBasicBlock::iterator e = mbb->end();
+ unsigned baseIndex = getInstructionIndex(mi);
+ unsigned start = getDefIndex(baseIndex);
unsigned end = start;
- // register can be dead by the instruction defining it but it can
- // only be killed by subsequent instructions
-
- for (LiveVariables::killed_iterator
- ki = lv_->dead_begin(*mi),
- ke = lv_->dead_end(*mi);
+ // a variable can be dead by the instruction defining it
+ for (KillIter ki = lv_->dead_begin(mi), ke = lv_->dead_end(mi);
ki != ke; ++ki) {
if (reg == ki->second) {
- end = getInstructionIndex(ki->first) + 1;
- DEBUG(std::cerr << " dead\n");
+ DEBUG(std::cerr << " dead");
+ end = getDefIndex(start) + 1;
goto exit;
}
}
- ++mi;
- for (MachineBasicBlock::iterator e = mbb->end(); mi != e; ++mi) {
- for (LiveVariables::killed_iterator
- ki = lv_->dead_begin(*mi),
- ke = lv_->dead_end(*mi);
+ // a variable can only be killed by subsequent instructions
+ do {
+ ++mi;
+ baseIndex += InstrSlots::NUM;
+ for (KillIter ki = lv_->killed_begin(mi), ke = lv_->killed_end(mi);
ki != ke; ++ki) {
if (reg == ki->second) {
- end = getInstructionIndex(ki->first) + 1;
- DEBUG(std::cerr << " dead\n");
+ DEBUG(std::cerr << " killed");
+ end = getUseIndex(baseIndex) + 1;
goto exit;
}
}
+ } while (mi != e);
- for (LiveVariables::killed_iterator
- ki = lv_->killed_begin(*mi),
- ke = lv_->killed_end(*mi);
- ki != ke; ++ki) {
- if (reg == ki->second) {
- end = getInstructionIndex(ki->first) + 1;
- DEBUG(std::cerr << " killed\n");
- goto exit;
- }
- }
- }
exit:
assert(start < end && "did not find end of interval?");
- Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg);
- if (r2iit != r2iMap_.end()) {
- Interval& interval = *r2iit->second;
- interval.addRange(start, end);
+ Reg2IntervalMap::iterator r2iit = r2iMap_.lower_bound(reg);
+ if (r2iit != r2iMap_.end() && r2iit->first == reg) {
+ r2iit->second->addRange(start, end);
}
else {
intervals_.push_back(Interval(reg));
- Interval& interval = intervals_.back();
// update interval index for this register
- bool inserted =
- r2iMap_.insert(std::make_pair(reg, --intervals_.end())).second;
- assert(inserted);
- interval.addRange(start, end);
+ r2iMap_.insert(r2iit, std::make_pair(reg, --intervals_.end()));
+ intervals_.back().addRange(start, end);
}
+ DEBUG(std::cerr << '\n');
}
void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb,
MachineBasicBlock::iterator mi,
unsigned reg)
{
- if (reg < MRegisterInfo::FirstVirtualRegister) {
+ if (MRegisterInfo::isPhysicalRegister(reg)) {
if (lv_->getAllocatablePhysicalRegisters()[reg]) {
handlePhysicalRegisterDef(mbb, mi, reg);
for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as)
@@ -275,144 +392,318 @@
unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) const
{
- assert(mi2iMap_.find(instr) != mi2iMap_.end() &&
- "instruction not assigned a number");
- return mi2iMap_.find(instr)->second;
+ Mi2IndexMap::const_iterator it = mi2iMap_.find(instr);
+ return (it == mi2iMap_.end() ?
+ std::numeric_limits<unsigned>::max() :
+ it->second);
+}
+
+MachineInstr* LiveIntervals::getInstructionFromIndex(unsigned index) const
+{
+ index /= InstrSlots::NUM; // convert index to vector index
+ assert(index < i2miMap_.size() &&
+ "index does not correspond to an instruction");
+ return i2miMap_[index];
}
/// computeIntervals - computes the live intervals for virtual
/// registers. for some ordering of the machine instructions [1,N] a
-/// live interval is an interval [i, j] where 1 <= i <= j <= N for
+/// live interval is an interval [i, j) where 1 <= i <= j < N for
/// which a variable is live
void LiveIntervals::computeIntervals()
{
- DEBUG(std::cerr << "computing live intervals:\n");
+ DEBUG(std::cerr << "********** COMPUTING LIVE INTERVALS **********\n");
+ DEBUG(std::cerr << "********** Function: "
+ << mf_->getFunction()->getName() << '\n');
for (MbbIndex2MbbMap::iterator
it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end();
it != itEnd; ++it) {
MachineBasicBlock* mbb = it->second;
- DEBUG(std::cerr << "machine basic block: "
- << mbb->getBasicBlock()->getName() << "\n");
+ DEBUG(std::cerr << mbb->getBasicBlock()->getName() << ":\n");
for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end();
mi != miEnd; ++mi) {
- MachineInstr* instr = *mi;
const TargetInstrDescriptor& tid =
- tm_->getInstrInfo().get(instr->getOpcode());
- DEBUG(std::cerr << "\t[" << getInstructionIndex(instr) << "] ";
- instr->print(std::cerr, *tm_););
+ tm_->getInstrInfo().get(mi->getOpcode());
+ DEBUG(std::cerr << getInstructionIndex(mi) << "\t";
+ mi->print(std::cerr, *tm_));
// handle implicit defs
for (const unsigned* id = tid.ImplicitDefs; *id; ++id)
handleRegisterDef(mbb, mi, *id);
// handle explicit defs
- for (int i = instr->getNumOperands() - 1; i >= 0; --i) {
- MachineOperand& mop = instr->getOperand(i);
+ for (int i = mi->getNumOperands() - 1; i >= 0; --i) {
+ MachineOperand& mop = mi->getOperand(i);
+ // handle register defs - build intervals
+ if (mop.isRegister() && mop.getReg() && mop.isDef())
+ handleRegisterDef(mbb, mi, mop.getReg());
+ }
+ }
+ }
+}
+
+unsigned LiveIntervals::rep(unsigned reg)
+{
+ Reg2RegMap::iterator it = r2rMap_.find(reg);
+ if (it != r2rMap_.end())
+ return it->second = rep(it->second);
+ return reg;
+}
+
+void LiveIntervals::joinIntervals()
+{
+ DEBUG(std::cerr << "********** JOINING INTERVALS ***********\n");
+
+ const TargetInstrInfo& tii = tm_->getInstrInfo();
- if (!mop.isRegister())
+ for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
+ mbbi != mbbe; ++mbbi) {
+ MachineBasicBlock* mbb = mbbi;
+ DEBUG(std::cerr << mbb->getBasicBlock()->getName() << ":\n");
+
+ for (MachineBasicBlock::iterator mi = mbb->begin(), mie = mbb->end();
+ mi != mie; ++mi) {
+ const TargetInstrDescriptor& tid =
+ tm_->getInstrInfo().get(mi->getOpcode());
+ DEBUG(std::cerr << getInstructionIndex(mi) << '\t';
+ mi->print(std::cerr, *tm_););
+
+ // we only join virtual registers with allocatable
+ // physical registers since we do not have liveness information
+ // on not allocatable physical registers
+ unsigned regA, regB;
+ if (tii.isMoveInstr(*mi, regA, regB) &&
+ (MRegisterInfo::isVirtualRegister(regA) ||
+ lv_->getAllocatablePhysicalRegisters()[regA]) &&
+ (MRegisterInfo::isVirtualRegister(regB) ||
+ lv_->getAllocatablePhysicalRegisters()[regB])) {
+
+ // get representative registers
+ regA = rep(regA);
+ regB = rep(regB);
+
+ // if they are already joined we continue
+ if (regA == regB)
continue;
- // handle defs - build intervals
- if (mop.isDef())
- handleRegisterDef(mbb, mi, mop.getAllocatedRegNum());
+ Reg2IntervalMap::iterator r2iA = r2iMap_.find(regA);
+ assert(r2iA != r2iMap_.end());
+ Reg2IntervalMap::iterator r2iB = r2iMap_.find(regB);
+ assert(r2iB != r2iMap_.end());
+
+ Intervals::iterator intA = r2iA->second;
+ Intervals::iterator intB = r2iB->second;
+
+ // both A and B are virtual registers
+ if (MRegisterInfo::isVirtualRegister(intA->reg) &&
+ MRegisterInfo::isVirtualRegister(intB->reg)) {
+
+ const TargetRegisterClass *rcA, *rcB;
+ rcA = mf_->getSSARegMap()->getRegClass(intA->reg);
+ rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
+ assert(rcA == rcB && "registers must be of the same class");
+
+ // if their intervals do not overlap we join them
+ if (!intB->overlaps(*intA)) {
+ intA->join(*intB);
+ r2iB->second = r2iA->second;
+ r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
+ intervals_.erase(intB);
+ }
+ }
+ else if (MRegisterInfo::isPhysicalRegister(intA->reg) ^
+ MRegisterInfo::isPhysicalRegister(intB->reg)) {
+ if (MRegisterInfo::isPhysicalRegister(intB->reg)) {
+ std::swap(regA, regB);
+ std::swap(intA, intB);
+ std::swap(r2iA, r2iB);
+ }
+
+ assert(MRegisterInfo::isPhysicalRegister(intA->reg) &&
+ MRegisterInfo::isVirtualRegister(intB->reg) &&
+ "A must be physical and B must be virtual");
+
+ if (!intA->overlaps(*intB) &&
+ !overlapsAliases(*intA, *intB)) {
+ intA->join(*intB);
+ r2iB->second = r2iA->second;
+ r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
+ intervals_.erase(intB);
+ }
+ }
}
}
}
+}
+
+bool LiveIntervals::overlapsAliases(const Interval& lhs,
+ const Interval& rhs) const
+{
+ assert(MRegisterInfo::isPhysicalRegister(lhs.reg) &&
+ "first interval must describe a physical register");
+
+ for (const unsigned* as = mri_->getAliasSet(lhs.reg); *as; ++as) {
+ Reg2IntervalMap::const_iterator r2i = r2iMap_.find(*as);
+ assert(r2i != r2iMap_.end() && "alias does not have interval?");
+ if (rhs.overlaps(*r2i->second))
+ return true;
+ }
- intervals_.sort(StartPointComp());
- DEBUG(std::copy(intervals_.begin(), intervals_.end(),
- std::ostream_iterator<Interval>(std::cerr, "\n")));
+ return false;
}
LiveIntervals::Interval::Interval(unsigned r)
- : reg(r), hint(0),
- weight((r < MRegisterInfo::FirstVirtualRegister ?
- std::numeric_limits<float>::max() : 0.0F))
+ : reg(r),
+ weight((MRegisterInfo::isPhysicalRegister(r) ?
+ std::numeric_limits<float>::infinity() : 0.0F))
{
}
+bool LiveIntervals::Interval::spilled() const
+{
+ return (weight == std::numeric_limits<float>::infinity() &&
+ MRegisterInfo::isVirtualRegister(reg));
+}
+
+// An example for liveAt():
+//
+// this = [1,4), liveAt(0) will return false. The instruction defining
+// this spans slots [0,3]. The interval belongs to an spilled
+// definition of the variable it represents. This is because slot 1 is
+// used (def slot) and spans up to slot 3 (store slot).
+//
+bool LiveIntervals::Interval::liveAt(unsigned index) const
+{
+ Range dummy(index, index+1);
+ Ranges::const_iterator r = std::upper_bound(ranges.begin(),
+ ranges.end(),
+ dummy);
+ if (r == ranges.begin())
+ return false;
+
+ --r;
+ return index >= r->first && index < r->second;
+}
+
+// An example for overlaps():
+//
+// 0: A = ...
+// 4: B = ...
+// 8: C = A + B ;; last use of A
+//
+// The live intervals should look like:
+//
+// A = [3, 11)
+// B = [7, x)
+// C = [11, y)
+//
+// A->overlaps(C) should return false since we want to be able to join
+// A and C.
+bool LiveIntervals::Interval::overlaps(const Interval& other) const
+{
+ Ranges::const_iterator i = ranges.begin();
+ Ranges::const_iterator ie = ranges.end();
+ Ranges::const_iterator j = other.ranges.begin();
+ Ranges::const_iterator je = other.ranges.end();
+ if (i->first < j->first) {
+ i = std::upper_bound(i, ie, *j);
+ if (i != ranges.begin()) --i;
+ }
+ else if (j->first < i->first) {
+ j = std::upper_bound(j, je, *i);
+ if (j != other.ranges.begin()) --j;
+ }
+
+ while (i != ie && j != je) {
+ if (i->first == j->first) {
+ return true;
+ }
+ else {
+ if (i->first > j->first) {
+ swap(i, j);
+ swap(ie, je);
+ }
+ assert(i->first < j->first);
+
+ if (i->second > j->first) {
+ return true;
+ }
+ else {
+ ++i;
+ }
+ }
+ }
+
+ return false;
+}
+
void LiveIntervals::Interval::addRange(unsigned start, unsigned end)
{
- DEBUG(std::cerr << "\t\t\tadding range: [" << start <<','<< end << ") -> ");
+ assert(start < end && "Invalid range to add!");
+ DEBUG(std::cerr << " +[" << start << ',' << end << ")");
//assert(start < end && "invalid range?");
Range range = std::make_pair(start, end);
Ranges::iterator it =
ranges.insert(std::upper_bound(ranges.begin(), ranges.end(), range),
range);
- mergeRangesForward(it);
- mergeRangesBackward(it);
- DEBUG(std::cerr << *this << '\n');
+ it = mergeRangesForward(it);
+ it = mergeRangesBackward(it);
}
-void LiveIntervals::Interval::mergeRangesForward(Ranges::iterator it)
+void LiveIntervals::Interval::join(const LiveIntervals::Interval& other)
{
- for (Ranges::iterator next = it + 1;
- next != ranges.end() && it->second >= next->first; ) {
- it->second = std::max(it->second, next->second);
- next = ranges.erase(next);
- }
-}
+ DEBUG(std::cerr << "\t\tjoining " << *this << " with " << other << '\n');
+ Ranges::iterator cur = ranges.begin();
-void LiveIntervals::Interval::mergeRangesBackward(Ranges::iterator it)
-{
- for (Ranges::iterator prev = it - 1;
- it != ranges.begin() && it->first <= prev->second; ) {
- it->first = std::min(it->first, prev->first);
- it->second = std::max(it->second, prev->second);
- it = ranges.erase(prev);
- prev = it - 1;
+ for (Ranges::const_iterator i = other.ranges.begin(),
+ e = other.ranges.end(); i != e; ++i) {
+ cur = ranges.insert(std::upper_bound(cur, ranges.end(), *i), *i);
+ cur = mergeRangesForward(cur);
+ cur = mergeRangesBackward(cur);
}
+ weight += other.weight;
+ ++numJoins;
}
-bool LiveIntervals::Interval::liveAt(unsigned index) const
+LiveIntervals::Interval::Ranges::iterator
+LiveIntervals::Interval::mergeRangesForward(Ranges::iterator it)
{
- Ranges::const_iterator r = ranges.begin();
- while (r != ranges.end() && index < (r->second - 1)) {
- if (index >= r->first)
- return true;
- ++r;
+ Ranges::iterator n;
+ while ((n = next(it)) != ranges.end()) {
+ if (n->first > it->second)
+ break;
+ it->second = std::max(it->second, n->second);
+ n = ranges.erase(n);
}
- return false;
+ return it;
}
-bool LiveIntervals::Interval::overlaps(const Interval& other) const
+LiveIntervals::Interval::Ranges::iterator
+LiveIntervals::Interval::mergeRangesBackward(Ranges::iterator it)
{
- Ranges::const_iterator i = ranges.begin();
- Ranges::const_iterator j = other.ranges.begin();
+ while (it != ranges.begin()) {
+ Ranges::iterator p = prior(it);
+ if (it->first > p->second)
+ break;
- while (i != ranges.end() && j != other.ranges.end()) {
- if (i->first < j->first) {
- if ((i->second - 1) > j->first) {
- return true;
- }
- else {
- ++i;
- }
- }
- else if (j->first < i->first) {
- if ((j->second - 1) > i->first) {
- return true;
- }
- else {
- ++j;
- }
- }
- else {
- return true;
- }
+ it->first = std::min(it->first, p->first);
+ it->second = std::max(it->second, p->second);
+ it = ranges.erase(p);
}
- return false;
+ return it;
}
std::ostream& llvm::operator<<(std::ostream& os,
const LiveIntervals::Interval& li)
{
os << "%reg" << li.reg << ',' << li.weight << " = ";
+ if (li.empty())
+ return os << "EMPTY";
for (LiveIntervals::Interval::Ranges::const_iterator
i = li.ranges.begin(), e = li.ranges.end(); i != e; ++i) {
os << "[" << i->first << "," << i->second << ")";
Index: llvm/lib/CodeGen/LiveIntervals.h
diff -u llvm/lib/CodeGen/LiveIntervals.h:1.11 llvm/lib/CodeGen/LiveIntervals.h:1.11.2.1
--- llvm/lib/CodeGen/LiveIntervals.h:1.11 Fri Jan 16 14:17:05 2004
+++ llvm/lib/CodeGen/LiveIntervals.h Mon Mar 1 17:58:13 2004
@@ -9,12 +9,12 @@
//
// This file implements the LiveInterval analysis pass. Given some
// numbering of each the machine instructions (in this implemention
-// depth-first order) an interval [i, j] is said to be a live interval
+// depth-first order) an interval [i, j) is said to be a live interval
// for register v if there is no instruction with number j' > j such
// that v is live at j' abd there is no instruction with number i' < i
// such that v is live at i'. In this implementation intervals can
-// have holes, i.e. an interval might look like [1,20], [50,65],
-// [1000,1001]
+// have holes, i.e. an interval might look like [1,20), [50,65),
+// [1000,1001)
//
//===----------------------------------------------------------------------===//
@@ -22,15 +22,13 @@
#define LLVM_CODEGEN_LIVEINTERVALS_H
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
-#include <iostream>
#include <list>
-#include <map>
namespace llvm {
class LiveVariables;
class MRegisterInfo;
+ class VirtRegMap;
class LiveIntervals : public MachineFunctionPass
{
@@ -39,20 +37,23 @@
typedef std::pair<unsigned, unsigned> Range;
typedef std::vector<Range> Ranges;
unsigned reg; // the register of this interval
- unsigned hint;
float weight; // weight of this interval (number of uses
// * 10^loopDepth)
- Ranges ranges; // the ranges this register is valid
+ Ranges ranges; // the ranges in which this register is live
Interval(unsigned r);
+ bool empty() const { return ranges.empty(); }
+
+ bool spilled() const;
+
unsigned start() const {
- assert(!ranges.empty() && "empty interval for register");
+ assert(!empty() && "empty interval for register");
return ranges.front().first;
}
unsigned end() const {
- assert(!ranges.empty() && "empty interval for register");
+ assert(!empty() && "empty interval for register");
return ranges.back().second;
}
@@ -66,10 +67,12 @@
void addRange(unsigned start, unsigned end);
+ void join(const Interval& other);
+
private:
- void mergeRangesForward(Ranges::iterator it);
+ Ranges::iterator mergeRangesForward(Ranges::iterator it);
- void mergeRangesBackward(Ranges::iterator it);
+ Ranges::iterator mergeRangesBackward(Ranges::iterator it);
};
struct StartPointComp {
@@ -85,7 +88,6 @@
};
typedef std::list<Interval> Intervals;
- typedef std::vector<MachineBasicBlock*> MachineBasicBlockPtrs;
private:
MachineFunction* mf_;
@@ -101,31 +103,76 @@
typedef std::map<MachineInstr*, unsigned> Mi2IndexMap;
Mi2IndexMap mi2iMap_;
+ typedef std::vector<MachineInstr*> Index2MiMap;
+ Index2MiMap i2miMap_;
+
typedef std::map<unsigned, Intervals::iterator> Reg2IntervalMap;
Reg2IntervalMap r2iMap_;
+ typedef std::map<unsigned, unsigned> Reg2RegMap;
+ Reg2RegMap r2rMap_;
+
Intervals intervals_;
public:
- virtual void getAnalysisUsage(AnalysisUsage &AU) const;
- Intervals& getIntervals() { return intervals_; }
- MachineBasicBlockPtrs getOrderedMachineBasicBlockPtrs() const {
- MachineBasicBlockPtrs result;
- for (MbbIndex2MbbMap::const_iterator
- it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end();
- it != itEnd; ++it) {
- result.push_back(it->second);
- }
- return result;
+ struct InstrSlots
+ {
+ enum {
+ LOAD = 0,
+ USE = 1,
+ DEF = 2,
+ STORE = 3,
+ NUM = 4,
+ };
+ };
+
+ static unsigned getBaseIndex(unsigned index) {
+ return index - (index % InstrSlots::NUM);
+ }
+ static unsigned getBoundaryIndex(unsigned index) {
+ return getBaseIndex(index + InstrSlots::NUM - 1);
+ }
+ static unsigned getLoadIndex(unsigned index) {
+ return getBaseIndex(index) + InstrSlots::LOAD;
+ }
+ static unsigned getUseIndex(unsigned index) {
+ return getBaseIndex(index) + InstrSlots::USE;
+ }
+ static unsigned getDefIndex(unsigned index) {
+ return getBaseIndex(index) + InstrSlots::DEF;
+ }
+ static unsigned getStoreIndex(unsigned index) {
+ return getBaseIndex(index) + InstrSlots::STORE;
}
- private:
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ virtual void releaseMemory();
+
/// runOnMachineFunction - pass entry point
- bool runOnMachineFunction(MachineFunction&);
+ virtual bool runOnMachineFunction(MachineFunction&);
+
+ Interval& getInterval(unsigned reg) {
+ assert(r2iMap_.count(reg)&& "Interval does not exist for register");
+ return *r2iMap_.find(reg)->second;
+ }
+
+ /// getInstructionIndex - returns the base index of instr
+ unsigned getInstructionIndex(MachineInstr* instr) const;
+ /// getInstructionFromIndex - given an index in any slot of an
+ /// instruction return a pointer the instruction
+ MachineInstr* getInstructionFromIndex(unsigned index) const;
+
+ Intervals& getIntervals() { return intervals_; }
+
+ void updateSpilledInterval(Interval& i, VirtRegMap& vrm, int slot);
+
+ private:
/// computeIntervals - compute live intervals
void computeIntervals();
+ /// joinIntervals - join compatible live intervals
+ void joinIntervals();
/// handleRegisterDef - update intervals for a register def
/// (calls handlePhysicalRegisterDef and
@@ -146,7 +193,10 @@
MachineBasicBlock::iterator mi,
unsigned reg);
- unsigned getInstructionIndex(MachineInstr* instr) const;
+ bool overlapsAliases(const Interval& lhs, const Interval& rhs) const;
+
+ /// rep - returns the representative of this register
+ unsigned rep(unsigned reg);
void printRegName(unsigned reg) const;
};
Index: llvm/lib/CodeGen/LiveVariables.cpp
diff -u llvm/lib/CodeGen/LiveVariables.cpp:1.15 llvm/lib/CodeGen/LiveVariables.cpp:1.15.2.1
--- llvm/lib/CodeGen/LiveVariables.cpp:1.15 Tue Jan 13 15:16:25 2004
+++ llvm/lib/CodeGen/LiveVariables.cpp Mon Mar 1 17:58:13 2004
@@ -28,12 +28,13 @@
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CFG.h"
#include "Support/DepthFirstIterator.h"
-
-namespace llvm {
+#include "Support/STLExtras.h"
+using namespace llvm;
static RegisterAnalysis<LiveVariables> X("livevars", "Live Variable Analysis");
@@ -41,9 +42,25 @@
LiveVariables::getMachineBasicBlockInfo(MachineBasicBlock *MBB) const{
return BBMap.find(MBB->getBasicBlock())->second;
}
+
+/// getIndexMachineBasicBlock() - Given a block index, return the
+/// MachineBasicBlock corresponding to it.
+MachineBasicBlock *LiveVariables::getIndexMachineBasicBlock(unsigned Idx) {
+ if (BBIdxMap.empty()) {
+ BBIdxMap.resize(BBMap.size());
+ for (std::map<const BasicBlock*, std::pair<MachineBasicBlock*, unsigned> >
+ ::iterator I = BBMap.begin(), E = BBMap.end(); I != E; ++I) {
+ assert(BBIdxMap.size() > I->second.second &&"Indices are not sequential");
+ assert(BBIdxMap[I->second.second] == 0 && "Multiple idx collision!");
+ BBIdxMap[I->second.second] = I->second.first;
+ }
+ }
+ assert(Idx < BBIdxMap.size() && "BB Index out of range!");
+ return BBIdxMap[Idx];
+}
LiveVariables::VarInfo &LiveVariables::getVarInfo(unsigned RegIdx) {
- assert(RegIdx >= MRegisterInfo::FirstVirtualRegister &&
+ assert(MRegisterInfo::isVirtualRegister(RegIdx) &&
"getVarInfo: not a virtual register!");
RegIdx -= MRegisterInfo::FirstVirtualRegister;
if (RegIdx >= VirtRegInfo.size()) {
@@ -131,29 +148,31 @@
for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
*AliasSet; ++AliasSet) {
- if (MachineInstr *LastUse = PhysRegInfo[*AliasSet]) {
- if (PhysRegUsed[*AliasSet])
- RegistersKilled.insert(std::make_pair(LastUse, *AliasSet));
+ unsigned Alias = *AliasSet;
+ if (MachineInstr *LastUse = PhysRegInfo[Alias]) {
+ if (PhysRegUsed[Alias])
+ RegistersKilled.insert(std::make_pair(LastUse, Alias));
else
- RegistersDead.insert(std::make_pair(LastUse, *AliasSet));
+ RegistersDead.insert(std::make_pair(LastUse, Alias));
}
- PhysRegInfo[*AliasSet] = MI;
- PhysRegUsed[*AliasSet] = false;
+ PhysRegInfo[Alias] = MI;
+ PhysRegUsed[Alias] = false;
}
}
bool LiveVariables::runOnMachineFunction(MachineFunction &MF) {
+ const TargetInstrInfo &TII = MF.getTarget().getInstrInfo();
+ RegInfo = MF.getTarget().getRegisterInfo();
+ assert(RegInfo && "Target doesn't have register information?");
+
// First time though, initialize AllocatablePhysicalRegisters for the target
if (AllocatablePhysicalRegisters.empty()) {
- const MRegisterInfo &MRI = *MF.getTarget().getRegisterInfo();
- assert(&MRI && "Target doesn't have register information?");
-
// Make space, initializing to false...
- AllocatablePhysicalRegisters.resize(MRegisterInfo::FirstVirtualRegister);
+ AllocatablePhysicalRegisters.resize(RegInfo->getNumRegs());
// Loop over all of the register classes...
- for (MRegisterInfo::regclass_iterator RCI = MRI.regclass_begin(),
- E = MRI.regclass_end(); RCI != E; ++RCI)
+ for (MRegisterInfo::regclass_iterator RCI = RegInfo->regclass_begin(),
+ E = RegInfo->regclass_end(); RCI != E; ++RCI)
// Loop over all of the allocatable registers in the function...
for (TargetRegisterClass::iterator I = (*RCI)->allocation_order_begin(MF),
E = (*RCI)->allocation_order_end(MF); I != E; ++I)
@@ -169,16 +188,12 @@
// physical register. This is a purely local property, because all physical
// register references as presumed dead across basic blocks.
//
- MachineInstr *PhysRegInfoA[MRegisterInfo::FirstVirtualRegister];
- bool PhysRegUsedA[MRegisterInfo::FirstVirtualRegister];
- std::fill(PhysRegInfoA, PhysRegInfoA+MRegisterInfo::FirstVirtualRegister,
- (MachineInstr*)0);
+ MachineInstr *PhysRegInfoA[RegInfo->getNumRegs()];
+ bool PhysRegUsedA[RegInfo->getNumRegs()];
+ std::fill(PhysRegInfoA, PhysRegInfoA+RegInfo->getNumRegs(), (MachineInstr*)0);
PhysRegInfo = PhysRegInfoA;
PhysRegUsed = PhysRegUsedA;
- const TargetInstrInfo &TII = MF.getTarget().getInstrInfo();
- RegInfo = MF.getTarget().getRegisterInfo();
-
/// Get some space for a respectable number of registers...
VirtRegInfo.resize(64);
@@ -198,7 +213,7 @@
// Loop over all of the instructions, processing them.
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
I != E; ++I) {
- MachineInstr *MI = *I;
+ MachineInstr *MI = I;
const TargetInstrDescriptor &MID = TII.get(MI->getOpcode());
// Process all of the operands of the instruction...
@@ -217,10 +232,10 @@
// Process all explicit uses...
for (unsigned i = 0; i != NumOperandsToProcess; ++i) {
MachineOperand &MO = MI->getOperand(i);
- if (MO.isUse()) {
- if (MO.isVirtualRegister() && !MO.getVRegValueOrNull()) {
+ if (MO.isUse() && MO.isRegister() && MO.getReg()) {
+ if (MRegisterInfo::isVirtualRegister(MO.getReg())){
HandleVirtRegUse(getVarInfo(MO.getReg()), MBB, MI);
- } else if (MO.isPhysicalRegister() &&
+ } else if (MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
AllocatablePhysicalRegisters[MO.getReg()]) {
HandlePhysRegUse(MO.getReg(), MI);
}
@@ -235,15 +250,15 @@
// Process all explicit defs...
for (unsigned i = 0; i != NumOperandsToProcess; ++i) {
MachineOperand &MO = MI->getOperand(i);
- if (MO.isDef()) {
- if (MO.isVirtualRegister()) {
+ if (MO.isDef() && MO.isRegister() && MO.getReg()) {
+ if (MRegisterInfo::isVirtualRegister(MO.getReg())) {
VarInfo &VRInfo = getVarInfo(MO.getReg());
assert(VRInfo.DefBlock == 0 && "Variable multiply defined!");
VRInfo.DefBlock = MBB; // Created here...
VRInfo.DefInst = MI;
VRInfo.Kills.push_back(std::make_pair(MBB, MI)); // Defaults to dead
- } else if (MO.isPhysicalRegister() &&
+ } else if (MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
AllocatablePhysicalRegisters[MO.getReg()]) {
HandlePhysRegDef(MO.getReg(), MI);
}
@@ -260,10 +275,11 @@
MachineBasicBlock *Succ = BBMap.find(*SI)->second.first;
// PHI nodes are guaranteed to be at the top of the block...
- for (MachineBasicBlock::iterator I = Succ->begin(), E = Succ->end();
- I != E && (*I)->getOpcode() == TargetInstrInfo::PHI; ++I) {
- MachineInstr *MI = *I;
- for (unsigned i = 1; ; i += 2)
+ for (MachineBasicBlock::iterator MI = Succ->begin(), ME = Succ->end();
+ MI != ME && MI->getOpcode() == TargetInstrInfo::PHI; ++MI) {
+ for (unsigned i = 1; ; i += 2) {
+ assert(MI->getNumOperands() > i+1 &&
+ "Didn't find an entry for our predecessor??");
if (MI->getOperand(i+1).getMachineBasicBlock() == MBB) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.getVRegValueOrNull()) {
@@ -274,12 +290,13 @@
break; // Found the PHI entry for this block...
}
}
+ }
}
}
// Loop over PhysRegInfo, killing any registers that are available at the
// end of the basic block. This also resets the PhysRegInfo map.
- for (unsigned i = 0, e = MRegisterInfo::FirstVirtualRegister; i != e; ++i)
+ for (unsigned i = 0, e = RegInfo->getNumRegs(); i != e; ++i)
if (PhysRegInfo[i])
HandlePhysRegDef(i, 0);
}
@@ -301,4 +318,44 @@
return false;
}
-} // End llvm namespace
+/// instructionChanged - When the address of an instruction changes, this
+/// method should be called so that live variables can update its internal
+/// data structures. This removes the records for OldMI, transfering them to
+/// the records for NewMI.
+void LiveVariables::instructionChanged(MachineInstr *OldMI,
+ MachineInstr *NewMI) {
+ // If the instruction defines any virtual registers, update the VarInfo for
+ // the instruction.
+ for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = NewMI->getOperand(i);
+ if (MO.isRegister() && MO.isDef() && MO.getReg() &&
+ MRegisterInfo::isVirtualRegister(MO.getReg())) {
+ unsigned Reg = MO.getReg();
+ VarInfo &VI = getVarInfo(Reg);
+ if (VI.DefInst == OldMI)
+ VI.DefInst = NewMI;
+ }
+ }
+
+ // Move the killed information over...
+ killed_iterator I, E;
+ tie(I, E) = killed_range(OldMI);
+ std::vector<unsigned> Regs;
+ for (killed_iterator A = I; A != E; ++A)
+ Regs.push_back(A->second);
+ RegistersKilled.erase(I, E);
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i)
+ RegistersKilled.insert(std::make_pair(NewMI, Regs[i]));
+ Regs.clear();
+
+
+ // Move the dead information over...
+ tie(I, E) = dead_range(OldMI);
+ for (killed_iterator A = I; A != E; ++A)
+ Regs.push_back(A->second);
+ RegistersDead.erase(I, E);
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i)
+ RegistersDead.insert(std::make_pair(NewMI, Regs[i]));
+}
Index: llvm/lib/CodeGen/MachineCodeEmitter.cpp
diff -u llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.14 llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.14.4.1
--- llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.14 Tue Nov 11 16:41:32 2003
+++ llvm/lib/CodeGen/MachineCodeEmitter.cpp Mon Mar 1 17:58:13 2004
@@ -15,8 +15,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Function.h"
#include <fstream>
-
-namespace llvm {
+using namespace llvm;
namespace {
struct DebugMachineCodeEmitter : public MachineCodeEmitter {
@@ -173,5 +172,3 @@
MachineCodeEmitter::createFilePrinterEmitter(MachineCodeEmitter &MCE) {
return new FilePrinterEmitter(MCE, std::cerr);
}
-
-} // End llvm namespace
Index: llvm/lib/CodeGen/MachineCodeForInstruction.cpp
diff -u llvm/lib/CodeGen/MachineCodeForInstruction.cpp:1.11 llvm/lib/CodeGen/MachineCodeForInstruction.cpp:1.11.2.1
--- llvm/lib/CodeGen/MachineCodeForInstruction.cpp:1.11 Sat Jan 10 13:16:26 2004
+++ llvm/lib/CodeGen/MachineCodeForInstruction.cpp Mon Mar 1 17:58:13 2004
@@ -24,10 +24,19 @@
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineInstrAnnot.h"
+#include "../Target/SparcV9/MachineInstrAnnot.h"
#include "llvm/Instruction.h"
using namespace llvm;
+MachineCodeForInstruction &MachineCodeForInstruction::get(const Instruction *I){
+ return *(MachineCodeForInstruction*)I->getOrCreateAnnotation(MCFI_AID);
+}
+void MachineCodeForInstruction::destroy(const Instruction *I) {
+ I->deleteAnnotation(MCFI_AID);
+}
+
+
+
AnnotationID llvm::MCFI_AID(
AnnotationManager::getID("CodeGen::MachineCodeForInstruction"));
@@ -60,9 +69,8 @@
for (unsigned i=0, N=tempVec.size(); i < N; i++)
delete tempVec[i];
- // Free the MachineInstr objects allocated, if any.
- for (unsigned i=0, N = size(); i < N; i++)
- delete (*this)[i];
+ // do not free the MachineInstr objects allocated. they are managed
+ // by the ilist in MachineBasicBlock
// Free the CallArgsDescriptor if it exists.
delete callArgsDesc;
Index: llvm/lib/CodeGen/MachineFunction.cpp
diff -u llvm/lib/CodeGen/MachineFunction.cpp:1.46 llvm/lib/CodeGen/MachineFunction.cpp:1.46.2.1
--- llvm/lib/CodeGen/MachineFunction.cpp:1.46 Sat Dec 20 04:20:58 2003
+++ llvm/lib/CodeGen/MachineFunction.cpp Mon Mar 1 17:58:13 2004
@@ -15,7 +15,6 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -23,7 +22,6 @@
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/Target/TargetCacheInfo.h"
#include "llvm/Function.h"
#include "llvm/iOther.h"
using namespace llvm;
@@ -34,6 +32,12 @@
namespace {
struct Printer : public MachineFunctionPass {
+ std::ostream *OS;
+ const std::string Banner;
+
+ Printer (std::ostream *_OS, const std::string &_Banner) :
+ OS (_OS), Banner (_Banner) { }
+
const char *getPassName() const { return "MachineFunction Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -41,14 +45,19 @@
}
bool runOnMachineFunction(MachineFunction &MF) {
- MF.dump();
+ (*OS) << Banner;
+ MF.print (*OS);
return false;
}
};
}
-FunctionPass *llvm::createMachineFunctionPrinterPass() {
- return new Printer();
+/// Returns a newly-created MachineFunction Printer pass. The default output
+/// stream is std::cerr; the default banner is empty.
+///
+FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS,
+ const std::string &Banner) {
+ return new Printer(OS, Banner);
}
namespace {
@@ -56,14 +65,6 @@
const char *getPassName() const { return "Machine Code Deleter"; }
bool runOnMachineFunction(MachineFunction &MF) {
- // Delete all of the MachineInstrs out of the function. When the sparc
- // backend gets fixed, this can be dramatically simpler, but actually
- // putting this stuff into the MachineBasicBlock destructor!
- for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E;
- ++BB)
- while (!BB->empty())
- delete BB->pop_back();
-
// Delete the annotation from the function now.
MachineFunction::destruct(MF.getFunction());
return true;
@@ -79,6 +80,7 @@
}
+
//===---------------------------------------------------------------------===//
// MachineFunction implementation
//===---------------------------------------------------------------------===//
@@ -111,18 +113,11 @@
// Print Constant Pool
getConstantPool()->print(OS);
- for (const_iterator BB = begin(); BB != end(); ++BB) {
- const BasicBlock *LBB = BB->getBasicBlock();
- OS << "\n" << LBB->getName() << " (" << (const void*)LBB << "):\n";
- for (MachineBasicBlock::const_iterator I = BB->begin(); I != BB->end();++I){
- OS << "\t";
- (*I)->print(OS, Target);
- }
- }
+ for (const_iterator BB = begin(); BB != end(); ++BB)
+ BB->print(OS);
OS << "\nEnd function \"" << Fn->getName() << "\"\n\n";
}
-
// The next two methods are used to construct and to retrieve
// the MachineCodeForFunction object for the given function.
// construct() -- Allocates and initializes for a given function and target
@@ -277,7 +272,7 @@
inline unsigned
SizeToAlignment(unsigned size, const TargetMachine& target)
{
- unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
+ const unsigned short cacheLineSize = 16;
if (size > (unsigned) cacheLineSize / 2)
return cacheLineSize;
else
Index: llvm/lib/CodeGen/MachineInstr.cpp
diff -u llvm/lib/CodeGen/MachineInstr.cpp:1.82 llvm/lib/CodeGen/MachineInstr.cpp:1.82.2.1
--- llvm/lib/CodeGen/MachineInstr.cpp:1.82 Sun Dec 14 07:24:17 2003
+++ llvm/lib/CodeGen/MachineInstr.cpp Mon Mar 1 17:58:13 2004
@@ -6,17 +6,22 @@
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
+//
+// Methods common to all machine instructions.
+//
+// FIXME: Now that MachineInstrs have parent pointers, they should always
+// print themselves using their MachineFunction's TargetMachine.
+//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Value.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/MRegisterInfo.h"
-
-namespace llvm {
+#include "Support/LeakDetector.h"
+using namespace llvm;
// Global variable holding an array of descriptors for machine instructions.
// The actual object needs to be created separately for each target machine.
@@ -25,15 +30,18 @@
// FIXME: This should be a property of the target so that more than one target
// at a time can be active...
//
-extern const TargetInstrDescriptor *TargetInstrDescriptors;
+namespace llvm {
+ extern const TargetInstrDescriptor *TargetInstrDescriptors;
+}
// Constructor for instructions with variable #operands
-MachineInstr::MachineInstr(MachineOpCode OpCode, unsigned numOperands)
- : opCode(OpCode),
- opCodeFlags(0),
+MachineInstr::MachineInstr(short opcode, unsigned numOperands)
+ : Opcode(opcode),
+ numImplicitRefs(0),
operands(numOperands, MachineOperand()),
- numImplicitRefs(0)
-{
+ parent(0) {
+ // Make sure that we get added to a machine basicblock
+ LeakDetector::addGarbageObject(this);
}
/// MachineInstr ctor - This constructor only does a _reserve_ of the operands,
@@ -41,50 +49,48 @@
/// add* methods below to fill up the operands, instead of the Set methods.
/// Eventually, the "resizing" ctors will be phased out.
///
-MachineInstr::MachineInstr(MachineOpCode Opcode, unsigned numOperands,
- bool XX, bool YY)
- : opCode(Opcode),
- opCodeFlags(0),
- numImplicitRefs(0)
-{
+MachineInstr::MachineInstr(short opcode, unsigned numOperands, bool XX, bool YY)
+ : Opcode(opcode), numImplicitRefs(0), parent(0) {
operands.reserve(numOperands);
+ // Make sure that we get added to a machine basicblock
+ LeakDetector::addGarbageObject(this);
}
/// MachineInstr ctor - Work exactly the same as the ctor above, except that the
/// MachineInstr is created and added to the end of the specified basic block.
///
-MachineInstr::MachineInstr(MachineBasicBlock *MBB, MachineOpCode Opcode,
+MachineInstr::MachineInstr(MachineBasicBlock *MBB, short opcode,
unsigned numOperands)
- : opCode(Opcode),
- opCodeFlags(0),
- numImplicitRefs(0)
-{
+ : Opcode(opcode), numImplicitRefs(0), parent(0) {
assert(MBB && "Cannot use inserting ctor with null basic block!");
operands.reserve(numOperands);
+ // Make sure that we get added to a machine basicblock
+ LeakDetector::addGarbageObject(this);
MBB->push_back(this); // Add instruction to end of basic block!
}
-
-// OperandComplete - Return true if it's illegal to add a new operand
-bool MachineInstr::OperandsComplete() const
+MachineInstr::~MachineInstr()
{
- int NumOperands = TargetInstrDescriptors[opCode].numOperands;
+ LeakDetector::removeGarbageObject(this);
+}
+
+/// OperandComplete - Return true if it's illegal to add a new operand
+///
+bool MachineInstr::OperandsComplete() const {
+ int NumOperands = TargetInstrDescriptors[Opcode].numOperands;
if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
return true; // Broken: we have all the operands of this instruction!
return false;
}
-
-//
-// Support for replacing opcode and operands of a MachineInstr in place.
-// This only resets the size of the operand vector and initializes it.
-// The new operands must be set explicitly later.
-//
-void MachineInstr::replace(MachineOpCode Opcode, unsigned numOperands)
-{
+/// replace - Support for replacing opcode and operands of a MachineInstr in
+/// place. This only resets the size of the operand vector and initializes it.
+/// The new operands must be set explicitly later.
+///
+void MachineInstr::replace(short opcode, unsigned numOperands) {
assert(getNumImplicitRefs() == 0 &&
"This is probably broken because implicit refs are going to be lost.");
- opCode = Opcode;
+ Opcode = opcode;
operands.clear();
operands.resize(numOperands, MachineOperand());
}
@@ -100,14 +106,13 @@
void
MachineInstr::SetMachineOperandConst(unsigned i,
- MachineOperand::MachineOperandType operandType,
- int64_t intValue)
-{
+ MachineOperand::MachineOperandType opTy,
+ int intValue) {
assert(i < getNumOperands()); // must be explicit op
- assert(TargetInstrDescriptors[opCode].resultPos != (int) i &&
+ assert(TargetInstrDescriptors[Opcode].resultPos != (int) i &&
"immed. constant cannot be defined");
- operands[i].opType = operandType;
+ operands[i].opType = opTy;
operands[i].value = NULL;
operands[i].immedVal = intValue;
operands[i].regNum = -1;
@@ -122,23 +127,24 @@
operands[i].regNum = regNum;
}
-void
-MachineInstr::SetRegForOperand(unsigned i, int regNum)
-{
+// Used only by the SPARC back-end.
+void MachineInstr::SetRegForOperand(unsigned i, int regNum) {
assert(i < getNumOperands()); // must be explicit op
operands[i].setRegForValue(regNum);
}
-void
-MachineInstr::SetRegForImplicitRef(unsigned i, int regNum)
-{
+// Used only by the SPARC back-end.
+void MachineInstr::SetRegForImplicitRef(unsigned i, int regNum) {
getImplicitOp(i).setRegForValue(regNum);
}
-
-// Substitute all occurrences of Value* oldVal with newVal in all operands
-// and all implicit refs.
-// If defsOnly == true, substitute defs only.
+/// substituteValue - Substitute all occurrences of Value* oldVal with newVal
+/// in all operands and all implicit refs. If defsOnly == true, substitute defs
+/// only.
+///
+/// FIXME: Fold this into its single caller, at SparcInstrSelection.cpp:2865,
+/// or make it a static function in that file.
+///
unsigned
MachineInstr::substituteValue(const Value* oldVal, Value* newVal,
bool defsOnly, bool notDefsAndUses,
@@ -178,32 +184,28 @@
return numSubst;
}
-
-void
-MachineInstr::dump() const
-{
+void MachineInstr::dump() const {
std::cerr << " " << *this;
}
-static inline std::ostream&
-OutputValue(std::ostream &os, const Value* val)
-{
+static inline std::ostream& OutputValue(std::ostream &os, const Value* val) {
os << "(val ";
os << (void*) val; // print address always
if (val && val->hasName())
- os << " " << val->getName() << ")"; // print name also, if available
+ os << " " << val->getName(); // print name also, if available
+ os << ")";
return os;
}
static inline void OutputReg(std::ostream &os, unsigned RegNo,
const MRegisterInfo *MRI = 0) {
- if (MRI) {
- if (RegNo < MRegisterInfo::FirstVirtualRegister)
+ if (!RegNo || MRegisterInfo::isPhysicalRegister(RegNo)) {
+ if (MRI)
os << "%" << MRI->get(RegNo).Name;
else
- os << "%reg" << RegNo;
+ os << "%mreg(" << RegNo << ")";
} else
- os << "%mreg(" << RegNo << ")";
+ os << "%reg" << RegNo;
}
static void print(const MachineOperand &MO, std::ostream &OS,
@@ -230,14 +232,14 @@
OS << "==";
}
if (MO.hasAllocatedReg())
- OutputReg(OS, MO.getAllocatedRegNum(), MRI);
+ OutputReg(OS, MO.getReg(), MRI);
break;
case MachineOperand::MO_CCRegister:
OS << "%ccreg";
OutputValue(OS, MO.getVRegValue());
if (MO.hasAllocatedReg()) {
OS << "==";
- OutputReg(OS, MO.getAllocatedRegNum(), MRI);
+ OutputReg(OS, MO.getReg(), MRI);
}
break;
case MachineOperand::MO_MachineRegister:
@@ -290,7 +292,7 @@
// Specialize printing if op#0 is definition
if (getNumOperands() && getOperand(0).isDef() && !getOperand(0).isUse()) {
- llvm::print(getOperand(0), OS, TM);
+ ::print(getOperand(0), OS, TM);
OS << " = ";
++StartOp; // Don't print this operand again!
}
@@ -301,7 +303,7 @@
if (i != StartOp)
OS << ",";
OS << " ";
- llvm::print(mop, OS, TM);
+ ::print(mop, OS, TM);
if (mop.isDef())
if (mop.isUse())
@@ -327,10 +329,19 @@
OS << "\n";
}
+namespace llvm {
+std::ostream &operator<<(std::ostream &os, const MachineInstr &MI) {
+ // If the instruction is embedded into a basic block, we can find the target
+ // info for the instruction.
+ if (const MachineBasicBlock *MBB = MI.getParent()) {
+ const MachineFunction *MF = MBB->getParent();
+ MI.print(os, MF->getTarget());
+ return os;
+ }
-std::ostream &operator<<(std::ostream& os, const MachineInstr& MI)
-{
- os << TargetInstrDescriptors[MI.opCode].Name;
+ // Otherwise, print it out in the "raw" format without symbolic register names
+ // and such.
+ os << TargetInstrDescriptors[MI.getOpcode()].Name;
for (unsigned i=0, N=MI.getNumOperands(); i < N; i++) {
os << "\t" << MI.getOperand(i);
@@ -359,8 +370,7 @@
return os << "\n";
}
-std::ostream &operator<<(std::ostream &OS, const MachineOperand &MO)
-{
+std::ostream &operator<<(std::ostream &OS, const MachineOperand &MO) {
if (MO.isHiBits32())
OS << "%lm(";
else if (MO.isLoBits32())
@@ -374,7 +384,7 @@
{
case MachineOperand::MO_VirtualRegister:
if (MO.hasAllocatedReg())
- OutputReg(OS, MO.getAllocatedRegNum());
+ OutputReg(OS, MO.getReg());
if (MO.getVRegValue()) {
if (MO.hasAllocatedReg()) OS << "==";
@@ -387,7 +397,7 @@
OutputValue(OS, MO.getVRegValue());
if (MO.hasAllocatedReg()) {
OS << "==";
- OutputReg(OS, MO.getAllocatedRegNum());
+ OutputReg(OS, MO.getReg());
}
break;
case MachineOperand::MO_MachineRegister:
@@ -433,12 +443,10 @@
break;
}
- if (MO.flags &
- (MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 |
- MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64))
+ if (MO.isHiBits32() || MO.isLoBits32() || MO.isHiBits64() || MO.isLoBits64())
OS << ")";
return OS;
}
-} // End llvm namespace
+}
Index: llvm/lib/CodeGen/MachineInstrAnnot.cpp
diff -u llvm/lib/CodeGen/MachineInstrAnnot.cpp:1.10 llvm/lib/CodeGen/MachineInstrAnnot.cpp:1.10.4.1
--- llvm/lib/CodeGen/MachineInstrAnnot.cpp:1.10 Tue Nov 11 16:41:32 2003
+++ llvm/lib/CodeGen/MachineInstrAnnot.cpp Mon Mar 1 17:58:13 2004
@@ -12,13 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/MachineInstrAnnot.h"
+#include "../Target/SparcV9/MachineInstrAnnot.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/iOther.h"
#include "llvm/Type.h"
-
-namespace llvm {
+using namespace llvm;
CallArgsDescriptor::CallArgsDescriptor(CallInst* _callInstr,
TmpInstruction* _retAddrReg,
@@ -77,5 +76,3 @@
assert(desc->getCallInst()==callInstr && "Incorrect call args descriptor?");
return desc;
}
-
-} // End llvm namespace
Index: llvm/lib/CodeGen/PHIElimination.cpp
diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.14 llvm/lib/CodeGen/PHIElimination.cpp:1.14.2.1
--- llvm/lib/CodeGen/PHIElimination.cpp:1.14 Sun Dec 14 07:24:17 2003
+++ llvm/lib/CodeGen/PHIElimination.cpp Mon Mar 1 17:58:13 2004
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
@@ -20,8 +21,8 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CFG.h"
-
-namespace llvm {
+#include "Support/STLExtras.h"
+using namespace llvm;
namespace {
struct PNE : public MachineFunctionPass {
@@ -55,28 +56,28 @@
}
-const PassInfo *PHIEliminationID = X.getPassInfo();
+const PassInfo *llvm::PHIEliminationID = X.getPassInfo();
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks.
///
bool PNE::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) {
- if (MBB.empty() || MBB.front()->getOpcode() != TargetInstrInfo::PHI)
+ if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
return false; // Quick exit for normal case...
LiveVariables *LV = getAnalysisToUpdate<LiveVariables>();
const TargetInstrInfo &MII = MF.getTarget().getInstrInfo();
const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
- while (MBB.front()->getOpcode() == TargetInstrInfo::PHI) {
- MachineInstr *MI = MBB.front();
+ while (MBB.front().getOpcode() == TargetInstrInfo::PHI) {
// Unlink the PHI node from the basic block... but don't delete the PHI yet
- MBB.erase(MBB.begin());
-
- assert(MI->getOperand(0).isVirtualRegister() &&
+ MachineBasicBlock::iterator begin = MBB.begin();
+ MachineInstr *MI = MBB.remove(begin);
+
+ assert(MRegisterInfo::isVirtualRegister(MI->getOperand(0).getReg()) &&
"PHI node doesn't write virt reg?");
- unsigned DestReg = MI->getOperand(0).getAllocatedRegNum();
+ unsigned DestReg = MI->getOperand(0).getReg();
// Create a new register for the incoming PHI arguments
const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(DestReg);
@@ -88,13 +89,13 @@
//
MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
while (AfterPHIsIt != MBB.end() &&
- (*AfterPHIsIt)->getOpcode() == TargetInstrInfo::PHI)
+ AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
++AfterPHIsIt; // Skip over all of the PHI nodes...
RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC);
// Update live variable information if there is any...
if (LV) {
- MachineInstr *PHICopy = *(AfterPHIsIt-1);
+ MachineInstr *PHICopy = --AfterPHIsIt;
// Add information to LiveVariables to know that the incoming value is
// killed. Note that because the value is defined in several places (once
@@ -142,22 +143,7 @@
// source path the PHI.
MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock();
- // Figure out where to insert the copy, which is at the end of the
- // predecessor basic block, but before any terminator/branch
- // instructions...
- MachineBasicBlock::iterator I = opBlock.end();
- if (I != opBlock.begin()) { // Handle empty blocks
- --I;
- // must backtrack over ALL the branches in the previous block
- while (MII.isTerminatorInstr((*I)->getOpcode()) &&
- I != opBlock.begin())
- --I;
-
- // move back to the first branch instruction so new instructions
- // are inserted right in front of it and not in front of a non-branch
- if (!MII.isTerminatorInstr((*I)->getOpcode()))
- ++I;
- }
+ MachineBasicBlock::iterator I = opBlock.getFirstTerminator();
// Check to make sure we haven't already emitted the copy for this block.
// This can happen because PHI nodes may have multiple entries for the
@@ -171,10 +157,10 @@
bool HaveNotEmitted = true;
if (I != opBlock.begin()) {
- MachineInstr *PrevInst = *(I-1);
+ MachineBasicBlock::iterator PrevInst = prior(I);
for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) {
MachineOperand &MO = PrevInst->getOperand(i);
- if (MO.isVirtualRegister() && MO.getReg() == IncomingReg)
+ if (MO.isRegister() && MO.getReg() == IncomingReg)
if (MO.isDef()) {
HaveNotEmitted = false;
break;
@@ -183,7 +169,7 @@
}
if (HaveNotEmitted) { // If the copy has not already been emitted, do it.
- assert(opVal.isVirtualRegister() &&
+ assert(MRegisterInfo::isVirtualRegister(opVal.getReg()) &&
"Machine PHI Operands must all be virtual registers!");
unsigned SrcReg = opVal.getReg();
RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC);
@@ -238,10 +224,10 @@
// Loop over all of the PHIs in this successor, checking to see if
// the register is being used...
for (MachineBasicBlock::iterator BBI = MBB->begin(), E=MBB->end();
- BBI != E && (*BBI)->getOpcode() == TargetInstrInfo::PHI;
+ BBI != E && BBI->getOpcode() == TargetInstrInfo::PHI;
++BBI)
- for (unsigned i = 1, e = (*BBI)->getNumOperands(); i < e; i += 2)
- if ((*BBI)->getOperand(i).getReg() == SrcReg) {
+ for (unsigned i = 1, e = BBI->getNumOperands(); i < e; i += 2)
+ if (BBI->getOperand(i).getReg() == SrcReg) {
ValueIsLive = true;
break;
}
@@ -251,8 +237,10 @@
// we can add a kill marker to the copy we inserted saying that it
// kills the incoming value!
//
- if (!ValueIsLive)
- LV->addVirtualRegisterKilled(SrcReg, &opBlock, *(I-1));
+ if (!ValueIsLive) {
+ MachineBasicBlock::iterator Prev = prior(I);
+ LV->addVirtualRegisterKilled(SrcReg, &opBlock, Prev);
+ }
}
}
}
@@ -260,8 +248,5 @@
// really delete the PHI instruction now!
delete MI;
}
-
return true;
}
-
-} // End llvm namespace
Index: llvm/lib/CodeGen/Passes.cpp
diff -u llvm/lib/CodeGen/Passes.cpp:1.5 llvm/lib/CodeGen/Passes.cpp:1.5.2.1
--- llvm/lib/CodeGen/Passes.cpp:1.5 Sun Dec 28 01:59:53 2003
+++ llvm/lib/CodeGen/Passes.cpp Mon Mar 1 17:58:13 2004
@@ -26,7 +26,7 @@
cl::Prefix,
cl::values(clEnumVal(simple, " simple register allocator"),
clEnumVal(local, " local register allocator"),
- clEnumVal(linearscan, " linear-scan global register allocator"),
+ clEnumVal(linearscan, " linear scan register allocator (experimental)"),
0),
cl::init(local));
}
Index: llvm/lib/CodeGen/PrologEpilogInserter.cpp
diff -u llvm/lib/CodeGen/PrologEpilogInserter.cpp:1.16 llvm/lib/CodeGen/PrologEpilogInserter.cpp:1.16.2.1
--- llvm/lib/CodeGen/PrologEpilogInserter.cpp:1.16 Sun Dec 14 07:24:16 2003
+++ llvm/lib/CodeGen/PrologEpilogInserter.cpp Mon Mar 1 17:58:13 2004
@@ -24,8 +24,7 @@
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
-
-namespace llvm {
+using namespace llvm;
namespace {
struct PEI : public MachineFunctionPass {
@@ -72,7 +71,7 @@
/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
-FunctionPass *createPrologEpilogCodeInserter() { return new PEI(); }
+FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }
/// saveCallerSavedRegisters - Scan the function for modified caller saved
@@ -99,28 +98,29 @@
return;
// This bitset contains an entry for each physical register for the target...
- std::vector<bool> ModifiedRegs(MRegisterInfo::FirstVirtualRegister);
+ std::vector<bool> ModifiedRegs(RegInfo->getNumRegs());
unsigned MaxCallFrameSize = 0;
bool HasCalls = false;
for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
- if ((*I)->getOpcode() == FrameSetupOpcode ||
- (*I)->getOpcode() == FrameDestroyOpcode) {
- assert((*I)->getNumOperands() == 1 && "Call Frame Setup/Destroy Pseudo"
+ if (I->getOpcode() == FrameSetupOpcode ||
+ I->getOpcode() == FrameDestroyOpcode) {
+ assert(I->getNumOperands() == 1 && "Call Frame Setup/Destroy Pseudo"
" instructions should have a single immediate argument!");
- unsigned Size = (*I)->getOperand(0).getImmedValue();
+ unsigned Size = I->getOperand(0).getImmedValue();
if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
HasCalls = true;
- RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I);
+ RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
} else {
- for (unsigned i = 0, e = (*I)->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = (*I)->getOperand(i);
- assert(!MO.isVirtualRegister() &&
- "Register allocation must be performed!");
- if (MO.isPhysicalRegister() && MO.isDef())
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = I->getOperand(i);
+ if (MO.isRegister() && MO.isDef()) {
+ assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
+ "Register allocation must be performed!");
ModifiedRegs[MO.getReg()] = true; // Register is modified
- }
+ }
+ }
++I;
}
@@ -173,8 +173,9 @@
const TargetInstrInfo &TII = Fn.getTarget().getInstrInfo();
for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI) {
// If last instruction is a return instruction, add an epilogue
- if (!FI->empty() && TII.isReturn(FI->back()->getOpcode())) {
- MBB = FI; I = MBB->end()-1;
+ if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
+ MBB = FI;
+ I = MBB->end(); --I;
for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
const TargetRegisterClass *RC = RegInfo->getRegClass(RegsToSave[i]);
@@ -201,8 +202,18 @@
unsigned StackAlignment = TFI.getStackAlignment();
- // Start at the beginning of the local area...
+ // Start at the beginning of the local area.
int Offset = TFI.getOffsetOfLocalArea();
+
+ // Check to see if there are any fixed sized objects that are preallocated in
+ // the local area. We currently don't support filling in holes in between
+ // fixed sized objects, so we just skip to the end of the last fixed sized
+ // preallocated object.
+ for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
+ int FixedOff = -FFI->getObjectOffset(i);
+ if (FixedOff > Offset) Offset = FixedOff;
+ }
+
for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
Offset += FFI->getObjectSize(i); // Allocate Size bytes...
@@ -214,8 +225,11 @@
FFI->setObjectOffset(i, -Offset); // Set the computed offset
}
- // Align the final stack pointer offset...
- Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;
+ // Align the final stack pointer offset, but only if there are calls in the
+ // function. This ensures that any calls to subroutines have their stack
+ // frames suitable aligned.
+ if (FFI->hasCalls())
+ Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;
// Set the final value of the stack pointer...
FFI->setStackSize(Offset-TFI.getOffsetOfLocalArea());
@@ -234,7 +248,7 @@
const TargetInstrInfo &TII = Fn.getTarget().getInstrInfo();
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
// If last instruction is a return instruction, add an epilogue
- if (!I->empty() && TII.isReturn(I->back()->getOpcode()))
+ if (!I->empty() && TII.isReturn(I->back().getOpcode()))
Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
}
}
@@ -252,13 +266,11 @@
for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
- for (unsigned i = 0, e = (*I)->getNumOperands(); i != e; ++i)
- if ((*I)->getOperand(i).isFrameIndex()) {
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+ if (I->getOperand(i).isFrameIndex()) {
// If this instruction has a FrameIndex operand, we need to use that
// target machine register info object to eliminate it.
MRI.eliminateFrameIndex(Fn, I);
break;
}
}
-
-} // End llvm namespace
Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.31 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.31.2.1
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.31 Fri Jan 16 14:33:13 2004
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Mon Mar 1 17:58:13 2004
@@ -10,56 +10,41 @@
// This file implements a linear scan register allocator.
//
//===----------------------------------------------------------------------===//
+
#define DEBUG_TYPE "regalloc"
#include "llvm/Function.h"
-#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LiveVariables.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/CFG.h"
#include "Support/Debug.h"
-#include "Support/DepthFirstIterator.h"
-#include "Support/Statistic.h"
-#include "Support/STLExtras.h"
+#include "LiveIntervals.h"
+#include "PhysRegTracker.h"
+#include "VirtRegMap.h"
+#include <algorithm>
+#include <iostream>
+
using namespace llvm;
namespace {
- Statistic<> numSpilled ("ra-linearscan", "Number of registers spilled");
- Statistic<> numReloaded("ra-linearscan", "Number of registers reloaded");
-
class RA : public MachineFunctionPass {
private:
MachineFunction* mf_;
const TargetMachine* tm_;
const MRegisterInfo* mri_;
- MachineFunction::iterator currentMbb_;
- MachineBasicBlock::iterator currentInstr_;
- typedef std::vector<const LiveIntervals::Interval*> IntervalPtrs;
- IntervalPtrs unhandled_, fixed_, active_, inactive_;
-
- typedef std::vector<unsigned> Regs;
- Regs tempUseOperands_;
- Regs tempDefOperands_;
-
- typedef std::vector<bool> RegMask;
- RegMask reserved_;
-
- unsigned regUse_[MRegisterInfo::FirstVirtualRegister];
- unsigned regUseBackup_[MRegisterInfo::FirstVirtualRegister];
+ LiveIntervals* li_;
+ typedef std::list<LiveIntervals::Interval*> IntervalPtrs;
+ IntervalPtrs unhandled_, fixed_, active_, inactive_, handled_;
+
+ std::auto_ptr<PhysRegTracker> prt_;
+ std::auto_ptr<VirtRegMap> vrm_;
+ std::auto_ptr<Spiller> spiller_;
- typedef std::map<unsigned, unsigned> Virt2PhysMap;
- Virt2PhysMap v2pMap_;
-
- typedef std::map<unsigned, int> Virt2StackSlotMap;
- Virt2StackSlotMap v2ssMap_;
-
- int instrAdded_;
+ typedef std::vector<float> SpillWeights;
+ SpillWeights spillWeights_;
public:
virtual const char* getPassName() const {
@@ -72,13 +57,18 @@
MachineFunctionPass::getAnalysisUsage(AU);
}
- private:
/// runOnMachineFunction - register allocate the whole function
bool runOnMachineFunction(MachineFunction&);
+ void releaseMemory();
+
+ private:
+ /// linearScan - the linear scan algorithm
+ void linearScan();
+
/// initIntervalSets - initializa the four interval sets:
/// unhandled, fixed, active and inactive
- void initIntervalSets(const LiveIntervals::Intervals& li);
+ void initIntervalSets(LiveIntervals::Intervals& li);
/// processActiveIntervals - expire old intervals and move
/// non-overlapping ones to the incative list
@@ -88,11 +78,13 @@
/// overlapping ones to the active list
void processInactiveIntervals(IntervalPtrs::value_type cur);
- /// assignStackSlotAtInterval - choose and spill
- /// interval. Currently we spill the interval with the last
- /// end point in the active and inactive lists and the current
- /// interval
- void assignStackSlotAtInterval(IntervalPtrs::value_type cur);
+ /// updateSpillWeights - updates the spill weights of the
+ /// specifed physical register and its weight
+ void updateSpillWeights(unsigned reg, SpillWeights::value_type weight);
+
+ /// assignRegOrStackSlotAtInterval - assign a register if one
+ /// is available, or spill.
+ void assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur);
///
/// register handling helpers
@@ -103,321 +95,146 @@
/// 0
unsigned getFreePhysReg(IntervalPtrs::value_type cur);
- /// physRegAvailable - returns true if the specifed physical
- /// register is available
- bool physRegAvailable(unsigned physReg);
-
- /// tempPhysRegAvailable - returns true if the specifed
- /// temporary physical register is available
- bool tempPhysRegAvailable(unsigned physReg);
-
- /// getFreeTempPhysReg - return a free temprorary physical
- /// register for this virtual register if we have one (should
- /// never return 0)
- unsigned getFreeTempPhysReg(unsigned virtReg);
-
- /// assignVirt2PhysReg - assigns the free physical register to
- /// the virtual register passed as arguments
- void assignVirt2PhysReg(unsigned virtReg, unsigned physReg);
-
- /// clearVirtReg - free the physical register associated with this
- /// virtual register and disassociate virtual->physical and
- /// physical->virtual mappings
- void clearVirtReg(unsigned virtReg);
-
/// assignVirt2StackSlot - assigns this virtual register to a
- /// stack slot
- void assignVirt2StackSlot(unsigned virtReg);
-
- /// getStackSlot - returns the offset of the specified
- /// register on the stack
- int getStackSlot(unsigned virtReg);
-
- /// spillVirtReg - spills the virtual register
- void spillVirtReg(unsigned virtReg);
-
- /// loadPhysReg - loads to the physical register the value of
- /// the virtual register specifed. Virtual register must have
- /// an assigned stack slot
- void loadVirt2PhysReg(unsigned virtReg, unsigned physReg);
-
- void markPhysRegFree(unsigned physReg);
- void markPhysRegNotFree(unsigned physReg);
-
- void backupRegUse() {
- memcpy(regUseBackup_, regUse_, sizeof(regUseBackup_));
- }
-
- void restoreRegUse() {
- memcpy(regUse_, regUseBackup_, sizeof(regUseBackup_));
- }
-
- void printVirt2PhysMap() const {
- std::cerr << "allocated registers:\n";
- for (Virt2PhysMap::const_iterator
- i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) {
- std::cerr << '[' << i->first << ','
- << mri_->getName(i->second) << "]\n";
- }
- std::cerr << '\n';
- }
+ /// stack slot. returns the stack slot
+ int assignVirt2StackSlot(unsigned virtReg);
void printIntervals(const char* const str,
RA::IntervalPtrs::const_iterator i,
RA::IntervalPtrs::const_iterator e) const {
if (str) std::cerr << str << " intervals:\n";
for (; i != e; ++i) {
- std::cerr << "\t\t" << **i << " -> ";
+ std::cerr << "\t" << **i << " -> ";
unsigned reg = (*i)->reg;
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- Virt2PhysMap::const_iterator it = v2pMap_.find(reg);
- reg = (it == v2pMap_.end() ? 0 : it->second);
+ if (MRegisterInfo::isVirtualRegister(reg)) {
+ reg = vrm_->getPhys(reg);
}
std::cerr << mri_->getName(reg) << '\n';
}
}
- void printFreeRegs(const char* const str,
- const TargetRegisterClass* rc) const {
- if (str) std::cerr << str << ':';
- for (TargetRegisterClass::iterator i =
- rc->allocation_order_begin(*mf_);
- i != rc->allocation_order_end(*mf_); ++i) {
- unsigned reg = *i;
- if (!regUse_[reg]) {
- std::cerr << ' ' << mri_->getName(reg);
- if (reserved_[reg]) std::cerr << "*";
- }
- }
- std::cerr << '\n';
- }
+// void verifyAssignment() const {
+// for (Virt2PhysMap::const_iterator i = v2pMap_.begin(),
+// e = v2pMap_.end(); i != e; ++i)
+// for (Virt2PhysMap::const_iterator i2 = next(i); i2 != e; ++i2)
+// if (MRegisterInfo::isVirtualRegister(i->second) &&
+// (i->second == i2->second ||
+// mri_->areAliases(i->second, i2->second))) {
+// const LiveIntervals::Interval
+// &in = li_->getInterval(i->second),
+// &in2 = li_->getInterval(i2->second);
+// if (in.overlaps(in2)) {
+// std::cerr << in << " overlaps " << in2 << '\n';
+// assert(0);
+// }
+// }
+// }
};
}
+void RA::releaseMemory()
+{
+ unhandled_.clear();
+ active_.clear();
+ inactive_.clear();
+ fixed_.clear();
+ handled_.clear();
+}
+
bool RA::runOnMachineFunction(MachineFunction &fn) {
mf_ = &fn;
tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo();
+ li_ = &getAnalysis<LiveIntervals>();
+ if (!prt_.get()) prt_.reset(new PhysRegTracker(*mri_));
+ vrm_.reset(new VirtRegMap(*mf_));
+ if (!spiller_.get()) spiller_.reset(createSpiller());
- initIntervalSets(getAnalysis<LiveIntervals>().getIntervals());
+ initIntervalSets(li_->getIntervals());
- v2pMap_.clear();
- v2ssMap_.clear();
- memset(regUse_, 0, sizeof(regUse_));
- memset(regUseBackup_, 0, sizeof(regUseBackup_));
-
- // FIXME: this will work only for the X86 backend. I need to
- // device an algorthm to select the minimal (considering register
- // aliasing) number of temp registers to reserve so that we have 2
- // registers for each register class available.
-
- // reserve R8: CH, CL
- // R16: CX, DI,
- // R32: ECX, EDI,
- // RFP: FP5, FP6
- reserved_.assign(MRegisterInfo::FirstVirtualRegister, false);
- reserved_[ 8] = true; /* CH */
- reserved_[ 9] = true; /* CL */
- reserved_[10] = true; /* CX */
- reserved_[12] = true; /* DI */
- reserved_[18] = true; /* ECX */
- reserved_[19] = true; /* EDI */
- reserved_[28] = true; /* FP5 */
- reserved_[29] = true; /* FP6 */
+ linearScan();
- // linear scan algorithm
+ spiller_->runOnMachineFunction(*mf_, *vrm_);
- DEBUG(printIntervals("\tunhandled", unhandled_.begin(), unhandled_.end()));
- DEBUG(printIntervals("\tfixed", fixed_.begin(), fixed_.end()));
- DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
- DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));
+ return true;
+}
+
+void RA::linearScan()
+{
+ // linear scan algorithm
+ DEBUG(std::cerr << "********** LINEAR SCAN **********\n");
+ DEBUG(std::cerr << "********** Function: "
+ << mf_->getFunction()->getName() << '\n');
+
+ DEBUG(printIntervals("unhandled", unhandled_.begin(), unhandled_.end()));
+ DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end()));
+ DEBUG(printIntervals("active", active_.begin(), active_.end()));
+ DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end()));
while (!unhandled_.empty() || !fixed_.empty()) {
// pick the interval with the earliest start point
IntervalPtrs::value_type cur;
if (fixed_.empty()) {
cur = unhandled_.front();
- unhandled_.erase(unhandled_.begin());
+ unhandled_.pop_front();
}
else if (unhandled_.empty()) {
cur = fixed_.front();
- fixed_.erase(fixed_.begin());
+ fixed_.pop_front();
}
else if (unhandled_.front()->start() < fixed_.front()->start()) {
cur = unhandled_.front();
- unhandled_.erase(unhandled_.begin());
+ unhandled_.pop_front();
}
else {
cur = fixed_.front();
- fixed_.erase(fixed_.begin());
+ fixed_.pop_front();
}
- DEBUG(std::cerr << *cur << '\n');
+ DEBUG(std::cerr << "\n*** CURRENT ***: " << *cur << '\n');
processActiveIntervals(cur);
processInactiveIntervals(cur);
// if this register is fixed we are done
- if (cur->reg < MRegisterInfo::FirstVirtualRegister) {
- markPhysRegNotFree(cur->reg);
+ if (MRegisterInfo::isPhysicalRegister(cur->reg)) {
+ prt_->addRegUse(cur->reg);
active_.push_back(cur);
+ handled_.push_back(cur);
}
// otherwise we are allocating a virtual register. try to find
// a free physical register or spill an interval in order to
// assign it one (we could spill the current though).
else {
- backupRegUse();
-
- // for every interval in inactive we overlap with, mark the
- // register as not free
- for (IntervalPtrs::const_iterator i = inactive_.begin(),
- e = inactive_.end(); i != e; ++i) {
- unsigned reg = (*i)->reg;
- if (reg >= MRegisterInfo::FirstVirtualRegister)
- reg = v2pMap_[reg];
-
- if (cur->overlaps(**i)) {
- markPhysRegNotFree(reg);
- }
- }
-
- // for every interval in fixed we overlap with,
- // mark the register as not free
- for (IntervalPtrs::const_iterator i = fixed_.begin(),
- e = fixed_.end(); i != e; ++i) {
- assert((*i)->reg < MRegisterInfo::FirstVirtualRegister &&
- "virtual register interval in fixed set?");
- if (cur->overlaps(**i))
- markPhysRegNotFree((*i)->reg);
- }
-
- DEBUG(std::cerr << "\tallocating current interval:\n");
-
- unsigned physReg = getFreePhysReg(cur);
- if (!physReg) {
- assignStackSlotAtInterval(cur);
- }
- else {
- restoreRegUse();
- assignVirt2PhysReg(cur->reg, physReg);
- active_.push_back(cur);
- }
+ assignRegOrStackSlotAtInterval(cur);
}
- DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
- DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end())); }
+ DEBUG(printIntervals("active", active_.begin(), active_.end()));
+ DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end()));
+ // DEBUG(verifyAssignment());
+ }
// expire any remaining active intervals
for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
unsigned reg = (*i)->reg;
- DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- reg = v2pMap_[reg];
- }
- markPhysRegFree(reg);
- }
- active_.clear();
- inactive_.clear();
-
- DEBUG(std::cerr << "finished register allocation\n");
- DEBUG(printVirt2PhysMap());
-
- DEBUG(std::cerr << "Rewrite machine code:\n");
- for (currentMbb_ = mf_->begin(); currentMbb_ != mf_->end(); ++currentMbb_) {
- instrAdded_ = 0;
-
- for (currentInstr_ = currentMbb_->begin();
- currentInstr_ != currentMbb_->end(); ++currentInstr_) {
-
- DEBUG(std::cerr << "\tinstruction: ";
- (*currentInstr_)->print(std::cerr, *tm_););
-
- // use our current mapping and actually replace and
- // virtual register with its allocated physical registers
- DEBUG(std::cerr << "\t\treplacing virtual registers with mapped "
- "physical registers:\n");
- for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
- i != e; ++i) {
- MachineOperand& op = (*currentInstr_)->getOperand(i);
- if (op.isVirtualRegister()) {
- unsigned virtReg = op.getAllocatedRegNum();
- unsigned physReg = v2pMap_[virtReg];
- if (physReg) {
- DEBUG(std::cerr << "\t\t\t%reg" << virtReg
- << " -> " << mri_->getName(physReg) << '\n');
- (*currentInstr_)->SetMachineOperandReg(i, physReg);
- }
- }
- }
-
- DEBUG(std::cerr << "\t\tloading temporarily used operands to "
- "registers:\n");
- for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
- i != e; ++i) {
- MachineOperand& op = (*currentInstr_)->getOperand(i);
- if (op.isVirtualRegister() && op.isUse() && !op.isDef()) {
- unsigned virtReg = op.getAllocatedRegNum();
- unsigned physReg = v2pMap_[virtReg];
- if (!physReg) {
- physReg = getFreeTempPhysReg(virtReg);
- loadVirt2PhysReg(virtReg, physReg);
- tempUseOperands_.push_back(virtReg);
- }
- (*currentInstr_)->SetMachineOperandReg(i, physReg);
- }
- }
-
- DEBUG(std::cerr << "\t\tclearing temporarily used operands:\n");
- for (unsigned i = 0, e = tempUseOperands_.size(); i != e; ++i) {
- clearVirtReg(tempUseOperands_[i]);
- }
- tempUseOperands_.clear();
-
- DEBUG(std::cerr << "\t\tassigning temporarily defined operands to "
- "registers:\n");
- for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
- i != e; ++i) {
- MachineOperand& op = (*currentInstr_)->getOperand(i);
- if (op.isVirtualRegister() && op.isDef()) {
- unsigned virtReg = op.getAllocatedRegNum();
- unsigned physReg = v2pMap_[virtReg];
- if (!physReg) {
- physReg = getFreeTempPhysReg(virtReg);
- }
- if (op.isUse()) { // def and use
- loadVirt2PhysReg(virtReg, physReg);
- }
- else {
- assignVirt2PhysReg(virtReg, physReg);
- }
- tempDefOperands_.push_back(virtReg);
- (*currentInstr_)->SetMachineOperandReg(i, physReg);
- }
- }
-
- DEBUG(std::cerr << "\t\tspilling temporarily defined operands "
- "of this instruction:\n");
- ++currentInstr_; // we want to insert after this instruction
- for (unsigned i = 0, e = tempDefOperands_.size(); i != e; ++i) {
- spillVirtReg(tempDefOperands_[i]);
- }
- --currentInstr_; // restore currentInstr_ iterator
- tempDefOperands_.clear();
- }
+ DEBUG(std::cerr << "\tinterval " << **i << " expired\n");
+ if (MRegisterInfo::isVirtualRegister(reg))
+ reg = vrm_->getPhys(reg);
+ prt_->delRegUse(reg);
}
- return true;
+ DEBUG(std::cerr << *vrm_);
}
-void RA::initIntervalSets(const LiveIntervals::Intervals& li)
+void RA::initIntervalSets(LiveIntervals::Intervals& li)
{
assert(unhandled_.empty() && fixed_.empty() &&
active_.empty() && inactive_.empty() &&
"interval sets should be empty on initialization");
- for (LiveIntervals::Intervals::const_iterator i = li.begin(), e = li.end();
+ for (LiveIntervals::Intervals::iterator i = li.begin(), e = li.end();
i != e; ++i) {
- if (i->reg < MRegisterInfo::FirstVirtualRegister)
+ if (MRegisterInfo::isPhysicalRegister(i->reg))
fixed_.push_back(&*i);
else
unhandled_.push_back(&*i);
@@ -432,20 +249,18 @@
// remove expired intervals
if ((*i)->expiredAt(cur->start())) {
DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- reg = v2pMap_[reg];
- }
- markPhysRegFree(reg);
+ if (MRegisterInfo::isVirtualRegister(reg))
+ reg = vrm_->getPhys(reg);
+ prt_->delRegUse(reg);
// remove from active
i = active_.erase(i);
}
// move inactive intervals to inactive list
else if (!(*i)->liveAt(cur->start())) {
- DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- reg = v2pMap_[reg];
- }
- markPhysRegFree(reg);
+ DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n");
+ if (MRegisterInfo::isVirtualRegister(reg))
+ reg = vrm_->getPhys(reg);
+ prt_->delRegUse(reg);
// add to inactive
inactive_.push_back(*i);
// remove from active
@@ -465,17 +280,16 @@
// remove expired intervals
if ((*i)->expiredAt(cur->start())) {
- DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
+ DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
// remove from inactive
i = inactive_.erase(i);
}
// move re-activated intervals in active list
else if ((*i)->liveAt(cur->start())) {
- DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- reg = v2pMap_[reg];
- }
- markPhysRegNotFree(reg);
+ DEBUG(std::cerr << "\t\tinterval " << **i << " active\n");
+ if (MRegisterInfo::isVirtualRegister(reg))
+ reg = vrm_->getPhys(reg);
+ prt_->addRegUse(reg);
// add to active
active_.push_back(*i);
// remove from inactive
@@ -487,281 +301,237 @@
}
}
-namespace {
- template <typename T>
- void updateWeight(T rw[], int reg, T w)
- {
- if (rw[reg] == std::numeric_limits<T>::max() ||
- w == std::numeric_limits<T>::max())
- rw[reg] = std::numeric_limits<T>::max();
- else
- rw[reg] += w;
- }
+void RA::updateSpillWeights(unsigned reg, SpillWeights::value_type weight)
+{
+ spillWeights_[reg] += weight;
+ for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as)
+ spillWeights_[*as] += weight;
}
-void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
+void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
{
- DEBUG(std::cerr << "\t\tassigning stack slot at interval "
- << *cur << ":\n");
+ DEBUG(std::cerr << "\tallocating current interval: ");
+
+ PhysRegTracker backupPrt = *prt_;
- // set all weights to zero
- float regWeight[MRegisterInfo::FirstVirtualRegister];
- for (unsigned i = 0; i < MRegisterInfo::FirstVirtualRegister; ++i)
- regWeight[i] = 0.0F;
+ spillWeights_.assign(mri_->getNumRegs(), 0.0);
- // for each interval in active that overlaps
+ // for each interval in active update spill weights
for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end();
i != e; ++i) {
- if (!cur->overlaps(**i))
- continue;
-
unsigned reg = (*i)->reg;
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- reg = v2pMap_[reg];
- }
- updateWeight(regWeight, reg, (*i)->weight);
- for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as)
- updateWeight(regWeight, *as, (*i)->weight);
+ if (MRegisterInfo::isVirtualRegister(reg))
+ reg = vrm_->getPhys(reg);
+ updateSpillWeights(reg, (*i)->weight);
}
- // for each interval in inactive that overlaps
+ // for every interval in inactive we overlap with, mark the
+ // register as not free and update spill weights
for (IntervalPtrs::const_iterator i = inactive_.begin(),
e = inactive_.end(); i != e; ++i) {
- if (!cur->overlaps(**i))
- continue;
-
- unsigned reg = (*i)->reg;
- if (reg >= MRegisterInfo::FirstVirtualRegister) {
- reg = v2pMap_[reg];
+ if (cur->overlaps(**i)) {
+ unsigned reg = (*i)->reg;
+ if (MRegisterInfo::isVirtualRegister(reg))
+ reg = vrm_->getPhys(reg);
+ prt_->addRegUse(reg);
+ updateSpillWeights(reg, (*i)->weight);
}
- updateWeight(regWeight, reg, (*i)->weight);
- for (const unsigned* as = mri_->getAliasSet(reg); *as; ++as)
- updateWeight(regWeight, *as, (*i)->weight);
}
- // for each fixed interval that overlaps
- for (IntervalPtrs::const_iterator i = fixed_.begin(), e = fixed_.end();
- i != e; ++i) {
- if (!cur->overlaps(**i))
- continue;
+ // for every interval in fixed we overlap with,
+ // mark the register as not free and update spill weights
+ for (IntervalPtrs::const_iterator i = fixed_.begin(),
+ e = fixed_.end(); i != e; ++i) {
+ if (cur->overlaps(**i)) {
+ unsigned reg = (*i)->reg;
+ prt_->addRegUse(reg);
+ updateSpillWeights(reg, (*i)->weight);
+ }
+ }
- assert((*i)->reg < MRegisterInfo::FirstVirtualRegister &&
- "virtual register interval in fixed set?");
- updateWeight(regWeight, (*i)->reg, (*i)->weight);
- for (const unsigned* as = mri_->getAliasSet((*i)->reg); *as; ++as)
- updateWeight(regWeight, *as, (*i)->weight);
+ unsigned physReg = getFreePhysReg(cur);
+ // restore the physical register tracker
+ *prt_ = backupPrt;
+ // if we find a free register, we are done: assign this virtual to
+ // the free physical register and add this interval to the active
+ // list.
+ if (physReg) {
+ DEBUG(std::cerr << mri_->getName(physReg) << '\n');
+ vrm_->assignVirt2Phys(cur->reg, physReg);
+ prt_->addRegUse(physReg);
+ active_.push_back(cur);
+ handled_.push_back(cur);
+ return;
}
+ DEBUG(std::cerr << "no free registers\n");
+
+ DEBUG(std::cerr << "\tassigning stack slot at interval "<< *cur << ":\n");
- float minWeight = std::numeric_limits<float>::max();
+ float minWeight = std::numeric_limits<float>::infinity();
unsigned minReg = 0;
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg);
for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
i != rc->allocation_order_end(*mf_); ++i) {
unsigned reg = *i;
- if (!reserved_[reg] && minWeight > regWeight[reg]) {
- minWeight = regWeight[reg];
+ if (minWeight > spillWeights_[reg]) {
+ minWeight = spillWeights_[reg];
minReg = reg;
}
}
+ DEBUG(std::cerr << "\t\tregister with min weight: "
+ << mri_->getName(minReg) << " (" << minWeight << ")\n");
- if (cur->weight < minWeight) {
- restoreRegUse();
- DEBUG(std::cerr << "\t\t\t\tspilling: " << *cur << '\n');
- assignVirt2StackSlot(cur->reg);
- }
- else {
- DEBUG(std::cerr << "\t\t\t\tfreeing: " << mri_->getName(minReg) << '\n');
- std::set<unsigned> toSpill;
- toSpill.insert(minReg);
- for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as)
- toSpill.insert(*as);
-
- std::vector<unsigned> spilled;
- for (IntervalPtrs::iterator i = active_.begin();
- i != active_.end(); ) {
- unsigned reg = (*i)->reg;
- if (reg >= MRegisterInfo::FirstVirtualRegister &&
- toSpill.find(v2pMap_[reg]) != toSpill.end() &&
- cur->overlaps(**i)) {
- spilled.push_back(v2pMap_[reg]);
- DEBUG(std::cerr << "\t\t\t\tspilling : " << **i << '\n');
- assignVirt2StackSlot(reg);
- i = active_.erase(i);
+ // if the current has the minimum weight, we need to modify it,
+ // push it back in unhandled and let the linear scan algorithm run
+ // again
+ if (cur->weight <= minWeight) {
+ DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n';);
+ int slot = vrm_->assignVirt2StackSlot(cur->reg);
+ li_->updateSpilledInterval(*cur, *vrm_, slot);
+
+ // if we didn't eliminate the interval find where to add it
+ // back to unhandled. We need to scan since unhandled are
+ // sorted on earliest start point and we may have changed our
+ // start point.
+ if (!cur->empty()) {
+ IntervalPtrs::iterator it = unhandled_.begin();
+ while (it != unhandled_.end() && (*it)->start() < cur->start())
+ ++it;
+ unhandled_.insert(it, cur);
+ }
+ return;
+ }
+
+ // push the current interval back to unhandled since we are going
+ // to re-run at least this iteration. Since we didn't modify it it
+ // should go back right in the front of the list
+ unhandled_.push_front(cur);
+
+ // otherwise we spill all intervals aliasing the register with
+ // minimum weight, rollback to the interval with the earliest
+ // start point and let the linear scan algorithm run again
+ assert(MRegisterInfo::isPhysicalRegister(minReg) &&
+ "did not choose a register to spill?");
+ std::vector<bool> toSpill(mri_->getNumRegs(), false);
+ toSpill[minReg] = true;
+ for (const unsigned* as = mri_->getAliasSet(minReg); *as; ++as)
+ toSpill[*as] = true;
+ unsigned earliestStart = cur->start();
+
+ for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
+ unsigned reg = (*i)->reg;
+ if (MRegisterInfo::isVirtualRegister(reg) &&
+ toSpill[vrm_->getPhys(reg)] &&
+ cur->overlaps(**i)) {
+ DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n');
+ earliestStart = std::min(earliestStart, (*i)->start());
+ int slot = vrm_->assignVirt2StackSlot((*i)->reg);
+ li_->updateSpilledInterval(**i, *vrm_, slot);
+ }
+ }
+ for (IntervalPtrs::iterator i = inactive_.begin();
+ i != inactive_.end(); ++i) {
+ unsigned reg = (*i)->reg;
+ if (MRegisterInfo::isVirtualRegister(reg) &&
+ toSpill[vrm_->getPhys(reg)] &&
+ cur->overlaps(**i)) {
+ DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n');
+ earliestStart = std::min(earliestStart, (*i)->start());
+ int slot = vrm_->assignVirt2StackSlot((*i)->reg);
+ li_->updateSpilledInterval(**i, *vrm_, slot);
+ }
+ }
+
+ DEBUG(std::cerr << "\t\trolling back to: " << earliestStart << '\n');
+ // scan handled in reverse order and undo each one, restoring the
+ // state of unhandled and fixed
+ while (!handled_.empty()) {
+ IntervalPtrs::value_type i = handled_.back();
+ // if this interval starts before t we are done
+ if (!i->empty() && i->start() < earliestStart)
+ break;
+ DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n');
+ handled_.pop_back();
+ IntervalPtrs::iterator it;
+ if ((it = find(active_.begin(), active_.end(), i)) != active_.end()) {
+ active_.erase(it);
+ if (MRegisterInfo::isPhysicalRegister(i->reg)) {
+ fixed_.push_front(i);
+ prt_->delRegUse(i->reg);
}
else {
- ++i;
+ prt_->delRegUse(vrm_->getPhys(i->reg));
+ vrm_->clearVirt(i->reg);
+ if (i->spilled()) {
+ if (!i->empty()) {
+ IntervalPtrs::iterator it = unhandled_.begin();
+ while (it != unhandled_.end() &&
+ (*it)->start() < i->start())
+ ++it;
+ unhandled_.insert(it, i);
+ }
+ }
+ else
+ unhandled_.push_front(i);
+
}
}
- for (IntervalPtrs::iterator i = inactive_.begin();
- i != inactive_.end(); ) {
- unsigned reg = (*i)->reg;
- if (reg >= MRegisterInfo::FirstVirtualRegister &&
- toSpill.find(v2pMap_[reg]) != toSpill.end() &&
- cur->overlaps(**i)) {
- DEBUG(std::cerr << "\t\t\t\tspilling : " << **i << '\n');
- assignVirt2StackSlot(reg);
- i = inactive_.erase(i);
+ else if ((it = find(inactive_.begin(), inactive_.end(), i)) != inactive_.end()) {
+ inactive_.erase(it);
+ if (MRegisterInfo::isPhysicalRegister(i->reg))
+ fixed_.push_front(i);
+ else {
+ vrm_->clearVirt(i->reg);
+ if (i->spilled()) {
+ if (!i->empty()) {
+ IntervalPtrs::iterator it = unhandled_.begin();
+ while (it != unhandled_.end() &&
+ (*it)->start() < i->start())
+ ++it;
+ unhandled_.insert(it, i);
+ }
+ }
+ else
+ unhandled_.push_front(i);
}
+ }
+ else {
+ if (MRegisterInfo::isPhysicalRegister(i->reg))
+ fixed_.push_front(i);
else {
- ++i;
+ vrm_->clearVirt(i->reg);
+ unhandled_.push_front(i);
}
}
-
- unsigned physReg = getFreePhysReg(cur);
- assert(physReg && "no free physical register after spill?");
-
- restoreRegUse();
- for (unsigned i = 0; i < spilled.size(); ++i)
- markPhysRegFree(spilled[i]);
-
- assignVirt2PhysReg(cur->reg, physReg);
- active_.push_back(cur);
}
-}
-
-bool RA::physRegAvailable(unsigned physReg)
-{
- assert(!reserved_[physReg] &&
- "cannot call this method with a reserved register");
- return !regUse_[physReg];
+ // scan the rest and undo each interval that expired after t and
+ // insert it in active (the next iteration of the algorithm will
+ // put it in inactive if required)
+ IntervalPtrs::iterator i = handled_.begin(), e = handled_.end();
+ for (; i != e; ++i) {
+ if (!(*i)->expiredAt(earliestStart) && (*i)->expiredAt(cur->start())) {
+ DEBUG(std::cerr << "\t\t\tundo changes for: " << **i << '\n');
+ active_.push_back(*i);
+ if (MRegisterInfo::isPhysicalRegister((*i)->reg))
+ prt_->addRegUse((*i)->reg);
+ else
+ prt_->addRegUse(vrm_->getPhys((*i)->reg));
+ }
+ }
}
unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
{
- DEBUG(std::cerr << "\t\tgetting free physical register: ");
const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg);
for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
i != rc->allocation_order_end(*mf_); ++i) {
unsigned reg = *i;
- if (!reserved_[reg] && !regUse_[reg]) {
- DEBUG(std::cerr << mri_->getName(reg) << '\n');
- return reg;
- }
- }
-
- DEBUG(std::cerr << "no free register\n");
- return 0;
-}
-
-bool RA::tempPhysRegAvailable(unsigned physReg)
-{
- assert(reserved_[physReg] &&
- "cannot call this method with a not reserved temp register");
-
- return !regUse_[physReg];
-}
-
-unsigned RA::getFreeTempPhysReg(unsigned virtReg)
-{
- DEBUG(std::cerr << "\t\tgetting free temporary physical register: ");
-
- const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
- // go in reverse allocation order for the temp registers
- for (TargetRegisterClass::iterator i = rc->allocation_order_end(*mf_) - 1;
- i != rc->allocation_order_begin(*mf_) - 1; --i) {
- unsigned reg = *i;
- if (reserved_[reg] && !regUse_[reg]) {
- DEBUG(std::cerr << mri_->getName(reg) << '\n');
+ if (prt_->isRegAvail(reg))
return reg;
- }
}
-
- assert(0 && "no free temporary physical register?");
return 0;
-}
-
-void RA::assignVirt2PhysReg(unsigned virtReg, unsigned physReg)
-{
- v2pMap_[virtReg] = physReg;
- markPhysRegNotFree(physReg);
-}
-
-void RA::clearVirtReg(unsigned virtReg)
-{
- Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
- assert(it != v2pMap_.end() &&
- "attempting to clear a not allocated virtual register");
- unsigned physReg = it->second;
- markPhysRegFree(physReg);
- v2pMap_[virtReg] = 0; // this marks that this virtual register
- // lives on the stack
- DEBUG(std::cerr << "\t\t\tcleared register " << mri_->getName(physReg)
- << "\n");
-}
-
-void RA::assignVirt2StackSlot(unsigned virtReg)
-{
- const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
- int frameIndex = mf_->getFrameInfo()->CreateStackObject(rc);
-
- bool inserted = v2ssMap_.insert(std::make_pair(virtReg, frameIndex)).second;
- assert(inserted &&
- "attempt to assign stack slot to already assigned register?");
- // if the virtual register was previously assigned clear the mapping
- // and free the virtual register
- if (v2pMap_.find(virtReg) != v2pMap_.end()) {
- clearVirtReg(virtReg);
- }
- else {
- v2pMap_[virtReg] = 0; // this marks that this virtual register
- // lives on the stack
- }
-}
-
-int RA::getStackSlot(unsigned virtReg)
-{
- // use lower_bound so that we can do a possibly O(1) insert later
- // if necessary
- Virt2StackSlotMap::iterator it = v2ssMap_.find(virtReg);
- assert(it != v2ssMap_.end() &&
- "attempt to get stack slot on register that does not live on the stack");
- return it->second;
-}
-
-void RA::spillVirtReg(unsigned virtReg)
-{
- DEBUG(std::cerr << "\t\t\tspilling register: " << virtReg);
- const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
- int frameIndex = getStackSlot(virtReg);
- DEBUG(std::cerr << " to stack slot #" << frameIndex << '\n');
- ++numSpilled;
- instrAdded_ += mri_->storeRegToStackSlot(*currentMbb_, currentInstr_,
- v2pMap_[virtReg], frameIndex, rc);
- clearVirtReg(virtReg);
-}
-
-void RA::loadVirt2PhysReg(unsigned virtReg, unsigned physReg)
-{
- DEBUG(std::cerr << "\t\t\tloading register: " << virtReg);
- const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
- int frameIndex = getStackSlot(virtReg);
- DEBUG(std::cerr << " from stack slot #" << frameIndex << '\n');
- ++numReloaded;
- instrAdded_ += mri_->loadRegFromStackSlot(*currentMbb_, currentInstr_,
- physReg, frameIndex, rc);
- assignVirt2PhysReg(virtReg, physReg);
-}
-
-void RA::markPhysRegFree(unsigned physReg)
-{
- assert(regUse_[physReg] != 0);
- --regUse_[physReg];
- for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
- physReg = *as;
- assert(regUse_[physReg] != 0);
- --regUse_[physReg];
- }
-}
-
-void RA::markPhysRegNotFree(unsigned physReg)
-{
- ++regUse_[physReg];
- for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
- physReg = *as;
- ++regUse_[physReg];
- }
}
FunctionPass* llvm::createLinearScanRegisterAllocator() {
Index: llvm/lib/CodeGen/RegAllocLocal.cpp
diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.37 llvm/lib/CodeGen/RegAllocLocal.cpp:1.37.2.1
--- llvm/lib/CodeGen/RegAllocLocal.cpp:1.37 Tue Jan 13 00:24:30 2004
+++ llvm/lib/CodeGen/RegAllocLocal.cpp Mon Mar 1 17:58:13 2004
@@ -1,10 +1,10 @@
//===-- RegAllocLocal.cpp - A BasicBlock generic register allocator -------===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// This register allocator allocates registers to a basic block at a time,
@@ -23,17 +23,16 @@
#include "llvm/Target/TargetMachine.h"
#include "Support/CommandLine.h"
#include "Support/Debug.h"
+#include "Support/DenseMap.h"
#include "Support/Statistic.h"
#include <iostream>
-
-namespace llvm {
+using namespace llvm;
namespace {
- Statistic<> NumSpilled ("ra-local", "Number of registers spilled");
- Statistic<> NumReloaded("ra-local", "Number of registers reloaded");
- cl::opt<bool> DisableKill("disable-kill", cl::Hidden,
- cl::desc("Disable register kill in local-ra"));
-
+ Statistic<> NumStores("ra-local", "Number of stores added");
+ Statistic<> NumLoads ("ra-local", "Number of loads added");
+ Statistic<> NumFolded("ra-local", "Number of loads/stores folded into "
+ "instructions");
class RA : public MachineFunctionPass {
const TargetMachine *TM;
MachineFunction *MF;
@@ -46,16 +45,21 @@
// Virt2PhysRegMap - This map contains entries for each virtual register
// that is currently available in a physical register.
+ DenseMap<unsigned, VirtReg2IndexFunctor> Virt2PhysRegMap;
+
+ unsigned &getVirt2PhysRegMapSlot(unsigned VirtReg) {
+ return Virt2PhysRegMap[VirtReg];
+ }
+
+ // PhysRegsUsed - This array is effectively a map, containing entries for
+ // each physical register that currently has a value (ie, it is in
+ // Virt2PhysRegMap). The value mapped to is the virtual register
+ // corresponding to the physical register (the inverse of the
+ // Virt2PhysRegMap), or 0. The value is set to 0 if this register is pinned
+ // because it is used by a future instruction. If the entry for a physical
+ // register is -1, then the physical register is "not in the map".
//
- std::map<unsigned, unsigned> Virt2PhysRegMap;
-
- // PhysRegsUsed - This map contains entries for each physical register that
- // currently has a value (ie, it is in Virt2PhysRegMap). The value mapped
- // to is the virtual register corresponding to the physical register (the
- // inverse of the Virt2PhysRegMap), or 0. The value is set to 0 if this
- // register is pinned because it is used by a future instruction.
- //
- std::map<unsigned, unsigned> PhysRegsUsed;
+ std::vector<int> PhysRegsUsed;
// PhysRegsUseOrder - This contains a list of the physical registers that
// currently have a virtual register value in them. This list provides an
@@ -75,16 +79,16 @@
std::vector<bool> VirtRegModified;
void markVirtRegModified(unsigned Reg, bool Val = true) {
- assert(Reg >= MRegisterInfo::FirstVirtualRegister && "Illegal VirtReg!");
+ assert(MRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!");
Reg -= MRegisterInfo::FirstVirtualRegister;
if (VirtRegModified.size() <= Reg) VirtRegModified.resize(Reg+1);
VirtRegModified[Reg] = Val;
}
bool isVirtRegModified(unsigned Reg) const {
- assert(Reg >= MRegisterInfo::FirstVirtualRegister && "Illegal VirtReg!");
+ assert(MRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!");
assert(Reg - MRegisterInfo::FirstVirtualRegister < VirtRegModified.size()
- && "Illegal virtual register!");
+ && "Illegal virtual register!");
return VirtRegModified[Reg - MRegisterInfo::FirstVirtualRegister];
}
@@ -93,14 +97,14 @@
if (PhysRegsUseOrder.back() == Reg) return; // Already most recently used
for (unsigned i = PhysRegsUseOrder.size(); i != 0; --i)
- if (areRegsEqual(Reg, PhysRegsUseOrder[i-1])) {
- unsigned RegMatch = PhysRegsUseOrder[i-1]; // remove from middle
- PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1);
- // Add it to the end of the list
- PhysRegsUseOrder.push_back(RegMatch);
- if (RegMatch == Reg)
- return; // Found an exact match, exit early
- }
+ if (areRegsEqual(Reg, PhysRegsUseOrder[i-1])) {
+ unsigned RegMatch = PhysRegsUseOrder[i-1]; // remove from middle
+ PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1);
+ // Add it to the end of the list
+ PhysRegsUseOrder.push_back(RegMatch);
+ if (RegMatch == Reg)
+ return; // Found an exact match, exit early
+ }
}
public:
@@ -109,8 +113,7 @@
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- if (!DisableKill)
- AU.addRequired<LiveVariables>();
+ AU.addRequired<LiveVariables>();
AU.addRequiredID(PHIEliminationID);
AU.addRequiredID(TwoAddressInstructionPassID);
MachineFunctionPass::getAnalysisUsage(AU);
@@ -150,7 +153,7 @@
/// the virtual register slot specified by VirtReg. It then updates the RA
/// data structures to indicate the fact that PhysReg is now available.
///
- void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+ void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
unsigned VirtReg, unsigned PhysReg);
/// spillPhysReg - This method spills the specified physical register into
@@ -158,7 +161,7 @@
/// true, then the request is ignored if the physical register does not
/// contain a virtual register.
///
- void spillPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+ void spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
unsigned PhysReg, bool OnlyVirtRegs = false);
/// assignVirtToPhysReg - This method updates local state so that we know
@@ -172,7 +175,7 @@
/// the way or spilled to memory.
///
void liberatePhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
- unsigned PhysReg);
+ unsigned PhysReg);
/// isPhysRegAvailable - Return true if the specified physical register is
/// free and available for use. This also includes checking to see if
@@ -184,22 +187,29 @@
/// specified register class. If not, return 0.
///
unsigned getFreeReg(const TargetRegisterClass *RC);
-
+
/// getReg - Find a physical register to hold the specified virtual
/// register. If all compatible physical registers are used, this method
/// spills the last used virtual register to the stack, and uses that
/// register.
///
- unsigned getReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
- unsigned VirtReg);
+ unsigned getReg(MachineBasicBlock &MBB, MachineInstr *MI,
+ unsigned VirtReg);
- /// reloadVirtReg - This method loads the specified virtual register into a
- /// physical register, returning the physical register chosen. This updates
- /// the regalloc data structures to reflect the fact that the virtual reg is
- /// now alive in a physical register, and the previous one isn't.
+ /// reloadVirtReg - This method transforms the specified specified virtual
+ /// register use to refer to a physical register. This method may do this
+ /// in one of several ways: if the register is available in a physical
+ /// register already, it uses that physical register. If the value is not
+ /// in a physical register, and if there are physical registers available,
+ /// it loads it into a register. If register pressure is high, and it is
+ /// possible, it tries to fold the load of the virtual register into the
+ /// instruction itself. It avoids doing this if register pressure is low to
+ /// improve the chance that subsequent instructions can use the reloaded
+ /// value. This method returns the modified instruction.
///
- unsigned reloadVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I, unsigned VirtReg);
+ MachineInstr *reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
+ unsigned OpNum);
+
void reloadPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
unsigned PhysReg);
@@ -224,11 +234,11 @@
}
-/// removePhysReg - This method marks the specified physical register as no
+/// removePhysReg - This method marks the specified physical register as no
/// longer being in use.
///
void RA::removePhysReg(unsigned PhysReg) {
- PhysRegsUsed.erase(PhysReg); // PhyReg no longer used
+ PhysRegsUsed[PhysReg] = -1; // PhyReg no longer used
std::vector<unsigned>::iterator It =
std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg);
@@ -241,9 +251,8 @@
/// virtual register slot specified by VirtReg. It then updates the RA data
/// structures to indicate the fact that PhysReg is now available.
///
-void RA::spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+void RA::spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned VirtReg, unsigned PhysReg) {
- if (!VirtReg && DisableKill) return;
assert(VirtReg && "Spilling a physical register is illegal!"
" Must not have appropriate kill for the register or use exists beyond"
" the intended one.");
@@ -260,9 +269,10 @@
int FrameIndex = getStackSpaceFor(VirtReg, RC);
DEBUG(std::cerr << " to stack slot #" << FrameIndex);
RegInfo->storeRegToStackSlot(MBB, I, PhysReg, FrameIndex, RC);
- ++NumSpilled; // Update statistics
+ ++NumStores; // Update statistics
}
- Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available
+
+ getVirt2PhysRegMapSlot(VirtReg) = 0; // VirtReg no longer available
DEBUG(std::cerr << "\n");
removePhysReg(PhysReg);
@@ -274,22 +284,19 @@
/// then the request is ignored if the physical register does not contain a
/// virtual register.
///
-void RA::spillPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+void RA::spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
unsigned PhysReg, bool OnlyVirtRegs) {
- std::map<unsigned, unsigned>::iterator PI = PhysRegsUsed.find(PhysReg);
- if (PI != PhysRegsUsed.end()) { // Only spill it if it's used!
- if (PI->second || !OnlyVirtRegs)
- spillVirtReg(MBB, I, PI->second, PhysReg);
+ if (PhysRegsUsed[PhysReg] != -1) { // Only spill it if it's used!
+ if (PhysRegsUsed[PhysReg] || !OnlyVirtRegs)
+ spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg);
} else {
// If the selected register aliases any other registers, we must make
// sure that one of the aliases isn't alive...
for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
- *AliasSet; ++AliasSet) {
- PI = PhysRegsUsed.find(*AliasSet);
- if (PI != PhysRegsUsed.end()) // Spill aliased register...
- if (PI->second || !OnlyVirtRegs)
- spillVirtReg(MBB, I, PI->second, *AliasSet);
- }
+ *AliasSet; ++AliasSet)
+ if (PhysRegsUsed[*AliasSet] != -1) // Spill aliased register...
+ if (PhysRegsUsed[*AliasSet] || !OnlyVirtRegs)
+ spillVirtReg(MBB, I, PhysRegsUsed[*AliasSet], *AliasSet);
}
}
@@ -299,12 +306,11 @@
/// register must not be used for anything else when this is called.
///
void RA::assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) {
- assert(PhysRegsUsed.find(PhysReg) == PhysRegsUsed.end() &&
- "Phys reg already assigned!");
+ assert(PhysRegsUsed[PhysReg] == -1 && "Phys reg already assigned!");
// Update information to note the fact that this register was just used, and
// it holds VirtReg.
PhysRegsUsed[PhysReg] = VirtReg;
- Virt2PhysRegMap[VirtReg] = PhysReg;
+ getVirt2PhysRegMapSlot(VirtReg) = PhysReg;
PhysRegsUseOrder.push_back(PhysReg); // New use of PhysReg
}
@@ -314,13 +320,13 @@
/// registers are all free...
///
bool RA::isPhysRegAvailable(unsigned PhysReg) const {
- if (PhysRegsUsed.count(PhysReg)) return false;
+ if (PhysRegsUsed[PhysReg] != -1) return false;
// If the selected register aliases any other allocated registers, it is
// not free!
for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
*AliasSet; ++AliasSet)
- if (PhysRegsUsed.count(*AliasSet)) // Aliased register in use?
+ if (PhysRegsUsed[*AliasSet] != -1) // Aliased register in use?
return false; // Can't use this reg then.
return true;
}
@@ -349,7 +355,7 @@
/// or spilled to memory.
///
void RA::liberatePhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
- unsigned PhysReg) {
+ unsigned PhysReg) {
// FIXME: This code checks to see if a register is available, but it really
// wants to know if a reg is available BEFORE the instruction executes. If
// called after killed operands are freed, it runs the risk of reallocating a
@@ -360,9 +366,9 @@
// Check to see if the register is directly used, not indirectly used through
// aliases. If aliased registers are the ones actually used, we cannot be
// sure that we will be able to save the whole thing if we do a reg-reg copy.
- std::map<unsigned, unsigned>::iterator PRUI = PhysRegsUsed.find(PhysReg);
- if (PRUI != PhysRegsUsed.end()) {
- unsigned VirtReg = PRUI->second; // The virtual register held...
+ if (PhysRegsUsed[PhysReg] != -1) {
+ // The virtual register held...
+ unsigned VirtReg = PhysRegsUsed[PhysReg]->second;
// Check to see if there is a compatible register available. If so, we can
// move the value into the new register...
@@ -371,12 +377,12 @@
if (unsigned NewReg = getFreeReg(RC)) {
// Emit the code to copy the value...
RegInfo->copyRegToReg(MBB, I, NewReg, PhysReg, RC);
-
+
// Update our internal state to indicate that PhysReg is available and Reg
// isn't.
- Virt2PhysRegMap.erase(VirtReg);
+ getVirt2PhysRegMapSlot[VirtReg] = 0;
removePhysReg(PhysReg); // Free the physreg
-
+
// Move reference over to new register...
assignVirtToPhysReg(VirtReg, NewReg);
return;
@@ -391,8 +397,8 @@
/// register. If all compatible physical registers are used, this method spills
/// the last used virtual register to the stack, and uses that register.
///
-unsigned RA::getReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
- unsigned VirtReg) {
+unsigned RA::getReg(MachineBasicBlock &MBB, MachineInstr *I,
+ unsigned VirtReg) {
const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg);
// First check to see if we have a free register of the requested type...
@@ -408,13 +414,13 @@
for (unsigned i = 0; PhysReg == 0; ++i) {
assert(i != PhysRegsUseOrder.size() &&
"Couldn't find a register of the appropriate class!");
-
+
unsigned R = PhysRegsUseOrder[i];
// We can only use this register if it holds a virtual register (ie, it
// can be spilled). Do not use it if it is an explicitly allocated
// physical register!
- assert(PhysRegsUsed.count(R) &&
+ assert(PhysRegsUsed[R] != -1 &&
"PhysReg in PhysRegsUseOrder, but is not allocated?");
if (PhysRegsUsed[R]) {
// If the current register is compatible, use it.
@@ -448,57 +454,87 @@
}
-/// reloadVirtReg - This method loads the specified virtual register into a
-/// physical register, returning the physical register chosen. This updates the
-/// regalloc data structures to reflect the fact that the virtual reg is now
-/// alive in a physical register, and the previous one isn't.
+/// reloadVirtReg - This method transforms the specified specified virtual
+/// register use to refer to a physical register. This method may do this in
+/// one of several ways: if the register is available in a physical register
+/// already, it uses that physical register. If the value is not in a physical
+/// register, and if there are physical registers available, it loads it into a
+/// register. If register pressure is high, and it is possible, it tries to
+/// fold the load of the virtual register into the instruction itself. It
+/// avoids doing this if register pressure is low to improve the chance that
+/// subsequent instructions can use the reloaded value. This method returns the
+/// modified instruction.
///
-unsigned RA::reloadVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I,
- unsigned VirtReg) {
- std::map<unsigned, unsigned>::iterator It = Virt2PhysRegMap.find(VirtReg);
- if (It != Virt2PhysRegMap.end()) {
- MarkPhysRegRecentlyUsed(It->second);
- return It->second; // Already have this value available!
+MachineInstr *RA::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
+ unsigned OpNum) {
+ unsigned VirtReg = MI->getOperand(OpNum).getReg();
+
+ // If the virtual register is already available, just update the instruction
+ // and return.
+ if (unsigned PR = getVirt2PhysRegMapSlot(VirtReg)) {
+ MarkPhysRegRecentlyUsed(PR); // Already have this value available!
+ MI->SetMachineOperandReg(OpNum, PR); // Assign the input register
+ return MI;
}
- unsigned PhysReg = getReg(MBB, I, VirtReg);
-
+ // Otherwise, we need to fold it into the current instruction, or reload it.
+ // If we have registers available to hold the value, use them.
const TargetRegisterClass *RC = MF->getSSARegMap()->getRegClass(VirtReg);
+ unsigned PhysReg = getFreeReg(RC);
int FrameIndex = getStackSpaceFor(VirtReg, RC);
+ if (PhysReg) { // Register is available, allocate it!
+ assignVirtToPhysReg(VirtReg, PhysReg);
+ } else { // No registers available.
+ // If we can fold this spill into this instruction, do so now.
+ MachineBasicBlock::iterator MII = MI;
+ if (RegInfo->foldMemoryOperand(MII, OpNum, FrameIndex)) {
+ ++NumFolded;
+ // Since we changed the address of MI, make sure to update live variables
+ // to know that the new instruction has the properties of the old one.
+ LV->instructionChanged(MI, MII);
+ return MII;
+ }
+
+ // It looks like we can't fold this virtual register load into this
+ // instruction. Force some poor hapless value out of the register file to
+ // make room for the new register, and reload it.
+ PhysReg = getReg(MBB, MI, VirtReg);
+ }
+
markVirtRegModified(VirtReg, false); // Note that this reg was just reloaded
DEBUG(std::cerr << " Reloading %reg" << VirtReg << " into "
<< RegInfo->getName(PhysReg) << "\n");
// Add move instruction(s)
- RegInfo->loadRegFromStackSlot(MBB, I, PhysReg, FrameIndex, RC);
- ++NumReloaded; // Update statistics
- return PhysReg;
+ RegInfo->loadRegFromStackSlot(MBB, MI, PhysReg, FrameIndex, RC);
+ ++NumLoads; // Update statistics
+
+ MI->SetMachineOperandReg(OpNum, PhysReg); // Assign the input register
+ return MI;
}
void RA::AllocateBasicBlock(MachineBasicBlock &MBB) {
// loop over each instruction
- MachineBasicBlock::iterator I = MBB.begin();
- for (; I != MBB.end(); ++I) {
- MachineInstr *MI = *I;
+ MachineBasicBlock::iterator MI = MBB.begin();
+ for (; MI != MBB.end(); ++MI) {
const TargetInstrDescriptor &TID = TM->getInstrInfo().get(MI->getOpcode());
DEBUG(std::cerr << "\nStarting RegAlloc of: " << *MI;
std::cerr << " Regs have values: ";
- for (std::map<unsigned, unsigned>::const_iterator
- I = PhysRegsUsed.begin(), E = PhysRegsUsed.end(); I != E; ++I)
- std::cerr << "[" << RegInfo->getName(I->first)
- << ",%reg" << I->second << "] ";
+ for (unsigned i = 0; i != RegInfo->getNumRegs(); ++i)
+ if (PhysRegsUsed[i] != -1)
+ std::cerr << "[" << RegInfo->getName(i)
+ << ",%reg" << PhysRegsUsed[i] << "] ";
std::cerr << "\n");
// Loop over the implicit uses, making sure that they are at the head of the
// use order list, so they don't get reallocated.
for (const unsigned *ImplicitUses = TID.ImplicitUses;
*ImplicitUses; ++ImplicitUses)
- MarkPhysRegRecentlyUsed(*ImplicitUses);
+ MarkPhysRegRecentlyUsed(*ImplicitUses);
// Get the used operands into registers. This has the potential to spill
// incoming values if we are out of registers. Note that we completely
@@ -506,67 +542,66 @@
// physical register is referenced by the instruction, that it is guaranteed
// to be live-in, or the input is badly hosed.
//
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
- if (MI->getOperand(i).isUse() &&
- !MI->getOperand(i).isDef() &&
- MI->getOperand(i).isVirtualRegister()){
- unsigned VirtSrcReg = MI->getOperand(i).getAllocatedRegNum();
- unsigned PhysSrcReg = reloadVirtReg(MBB, I, VirtSrcReg);
- MI->SetMachineOperandReg(i, PhysSrcReg); // Assign the input register
+ for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
+ MachineOperand& MO = MI->getOperand(i);
+ // here we are looking for only used operands (never def&use)
+ if (!MO.isDef() && MO.isRegister() && MO.getReg() &&
+ MRegisterInfo::isVirtualRegister(MO.getReg()))
+ MI = reloadVirtReg(MBB, MI, i);
+ }
+
+ // If this instruction is the last user of anything in registers, kill the
+ // value, freeing the register being used, so it doesn't need to be
+ // spilled to memory.
+ //
+ for (LiveVariables::killed_iterator KI = LV->killed_begin(MI),
+ KE = LV->killed_end(MI); KI != KE; ++KI) {
+ unsigned VirtReg = KI->second;
+ unsigned PhysReg = VirtReg;
+ if (MRegisterInfo::isVirtualRegister(VirtReg)) {
+ // If the virtual register was never materialized into a register, it
+ // might not be in the map, but it won't hurt to zero it out anyway.
+ unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg);
+ PhysReg = PhysRegSlot;
+ PhysRegSlot = 0;
}
-
- if (!DisableKill) {
- // If this instruction is the last user of anything in registers, kill the
- // value, freeing the register being used, so it doesn't need to be
- // spilled to memory.
- //
- for (LiveVariables::killed_iterator KI = LV->killed_begin(MI),
- KE = LV->killed_end(MI); KI != KE; ++KI) {
- unsigned VirtReg = KI->second;
- unsigned PhysReg = VirtReg;
- if (VirtReg >= MRegisterInfo::FirstVirtualRegister) {
- std::map<unsigned, unsigned>::iterator I =
- Virt2PhysRegMap.find(VirtReg);
- assert(I != Virt2PhysRegMap.end());
- PhysReg = I->second;
- Virt2PhysRegMap.erase(I);
- }
- if (PhysReg) {
- DEBUG(std::cerr << " Last use of " << RegInfo->getName(PhysReg)
- << "[%reg" << VirtReg <<"], removing it from live set\n");
- removePhysReg(PhysReg);
- }
+ if (PhysReg) {
+ DEBUG(std::cerr << " Last use of " << RegInfo->getName(PhysReg)
+ << "[%reg" << VirtReg <<"], removing it from live set\n");
+ removePhysReg(PhysReg);
}
}
// Loop over all of the operands of the instruction, spilling registers that
// are defined, and marking explicit destinations in the PhysRegsUsed map.
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
- if (MI->getOperand(i).isDef() &&
- MI->getOperand(i).isPhysicalRegister()) {
- unsigned Reg = MI->getOperand(i).getAllocatedRegNum();
- spillPhysReg(MBB, I, Reg, true); // Spill any existing value in the reg
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand& MO = MI->getOperand(i);
+ if (MO.isDef() && MO.isRegister() && MO.getReg() &&
+ MRegisterInfo::isPhysicalRegister(MO.getReg())) {
+ unsigned Reg = MO.getReg();
+ spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in the reg
PhysRegsUsed[Reg] = 0; // It is free and reserved now
PhysRegsUseOrder.push_back(Reg);
for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
*AliasSet; ++AliasSet) {
- PhysRegsUseOrder.push_back(*AliasSet);
- PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
+ PhysRegsUseOrder.push_back(*AliasSet);
+ PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
}
}
+ }
// Loop over the implicit defs, spilling them as well.
for (const unsigned *ImplicitDefs = TID.ImplicitDefs;
*ImplicitDefs; ++ImplicitDefs) {
unsigned Reg = *ImplicitDefs;
- spillPhysReg(MBB, I, Reg);
+ spillPhysReg(MBB, MI, Reg, true);
PhysRegsUseOrder.push_back(Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now
for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
*AliasSet; ++AliasSet) {
- PhysRegsUseOrder.push_back(*AliasSet);
- PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
+ PhysRegsUseOrder.push_back(*AliasSet);
+ PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
}
}
@@ -575,71 +610,65 @@
// implicit defs and assign them to a register, spilling incoming values if
// we need to scavenge a register.
//
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
- if (MI->getOperand(i).isDef() &&
- MI->getOperand(i).isVirtualRegister()) {
- unsigned DestVirtReg = MI->getOperand(i).getAllocatedRegNum();
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand& MO = MI->getOperand(i);
+ if (MO.isDef() && MO.isRegister() && MO.getReg() &&
+ MRegisterInfo::isVirtualRegister(MO.getReg())) {
+ unsigned DestVirtReg = MO.getReg();
unsigned DestPhysReg;
// If DestVirtReg already has a value, use it.
- std::map<unsigned, unsigned>::iterator DestI =
- Virt2PhysRegMap.find(DestVirtReg);
- if (DestI != Virt2PhysRegMap.end()) {
- DestPhysReg = DestI->second;
- }
- else {
- DestPhysReg = getReg(MBB, I, DestVirtReg);
- }
+ if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg)))
+ DestPhysReg = getReg(MBB, MI, DestVirtReg);
markVirtRegModified(DestVirtReg);
MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register
}
+ }
- if (!DisableKill) {
- // If this instruction defines any registers that are immediately dead,
- // kill them now.
- //
- for (LiveVariables::killed_iterator KI = LV->dead_begin(MI),
- KE = LV->dead_end(MI); KI != KE; ++KI) {
- unsigned VirtReg = KI->second;
- unsigned PhysReg = VirtReg;
- if (VirtReg >= MRegisterInfo::FirstVirtualRegister) {
- std::map<unsigned, unsigned>::iterator I =
- Virt2PhysRegMap.find(VirtReg);
- assert(I != Virt2PhysRegMap.end());
- PhysReg = I->second;
- Virt2PhysRegMap.erase(I);
- }
+ // If this instruction defines any registers that are immediately dead,
+ // kill them now.
+ //
+ for (LiveVariables::killed_iterator KI = LV->dead_begin(MI),
+ KE = LV->dead_end(MI); KI != KE; ++KI) {
+ unsigned VirtReg = KI->second;
+ unsigned PhysReg = VirtReg;
+ if (MRegisterInfo::isVirtualRegister(VirtReg)) {
+ unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg);
+ PhysReg = PhysRegSlot;
+ assert(PhysReg != 0);
+ PhysRegSlot = 0;
+ }
- if (PhysReg) {
- DEBUG(std::cerr << " Register " << RegInfo->getName(PhysReg)
- << " [%reg" << VirtReg
- << "] is never used, removing it frame live list\n");
- removePhysReg(PhysReg);
- }
+ if (PhysReg) {
+ DEBUG(std::cerr << " Register " << RegInfo->getName(PhysReg)
+ << " [%reg" << VirtReg
+ << "] is never used, removing it frame live list\n");
+ removePhysReg(PhysReg);
}
}
}
- // Rewind the iterator to point to the first flow control instruction...
- const TargetInstrInfo &TII = TM->getInstrInfo();
- I = MBB.end();
- while (I != MBB.begin() && TII.isTerminatorInstr((*(I-1))->getOpcode()))
- --I;
+ MI = MBB.getFirstTerminator();
// Spill all physical registers holding virtual registers now.
- while (!PhysRegsUsed.empty())
- if (unsigned VirtReg = PhysRegsUsed.begin()->second)
- spillVirtReg(MBB, I, VirtReg, PhysRegsUsed.begin()->first);
- else
- removePhysReg(PhysRegsUsed.begin()->first);
-
- for (std::map<unsigned, unsigned>::iterator I = Virt2PhysRegMap.begin(),
- E = Virt2PhysRegMap.end(); I != E; ++I)
- std::cerr << "Register still mapped: " << I->first << " -> "
- << I->second << "\n";
+ for (unsigned i = 0, e = RegInfo->getNumRegs(); i != e; ++i)
+ if (PhysRegsUsed[i] != -1)
+ if (unsigned VirtReg = PhysRegsUsed[i])
+ spillVirtReg(MBB, MI, VirtReg, i);
+ else
+ removePhysReg(i);
+
+#ifndef NDEBUG
+ bool AllOk = true;
+ for (unsigned i = MRegisterInfo::FirstVirtualRegister,
+ e = MF->getSSARegMap()->getLastVirtReg(); i <= e; ++i)
+ if (unsigned PR = Virt2PhysRegMap[i]) {
+ std::cerr << "Register still mapped: " << i << " -> " << PR << "\n";
+ AllOk = false;
+ }
+ assert(AllOk && "Virtual registers still in phys regs?");
+#endif
- assert(Virt2PhysRegMap.empty() && "Virtual registers still in phys regs?");
-
// Clear any physical register which appear live at the end of the basic
// block, but which do not hold any virtual registers. e.g., the stack
// pointer.
@@ -654,9 +683,13 @@
MF = &Fn;
TM = &Fn.getTarget();
RegInfo = TM->getRegisterInfo();
+ LV = &getAnalysis<LiveVariables>();
- if (!DisableKill)
- LV = &getAnalysis<LiveVariables>();
+ PhysRegsUsed.assign(RegInfo->getNumRegs(), -1);
+
+ // initialize the virtual->physical register map to have a 'null'
+ // mapping for all virtual registers
+ Virt2PhysRegMap.grow(MF->getSSARegMap()->getLastVirtReg());
// Loop over all of the basic blocks, eliminating virtual register references
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
@@ -664,12 +697,12 @@
AllocateBasicBlock(*MBB);
StackSlotForVirtReg.clear();
+ PhysRegsUsed.clear();
VirtRegModified.clear();
+ Virt2PhysRegMap.clear();
return true;
}
-FunctionPass *createLocalRegisterAllocator() {
+FunctionPass *llvm::createLocalRegisterAllocator() {
return new RA();
}
-
-} // End llvm namespace
Index: llvm/lib/CodeGen/RegAllocSimple.cpp
diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.47 llvm/lib/CodeGen/RegAllocSimple.cpp:1.47.2.1
--- llvm/lib/CodeGen/RegAllocSimple.cpp:1.47 Sun Dec 14 07:24:16 2003
+++ llvm/lib/CodeGen/RegAllocSimple.cpp Mon Mar 1 17:58:13 2004
@@ -24,13 +24,13 @@
#include "llvm/Target/TargetMachine.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
+#include "Support/STLExtras.h"
#include <iostream>
-
-namespace llvm {
+using namespace llvm;
namespace {
- Statistic<> NumSpilled ("ra-simple", "Number of registers spilled");
- Statistic<> NumReloaded("ra-simple", "Number of registers reloaded");
+ Statistic<> NumStores("ra-simple", "Number of stores added");
+ Statistic<> NumLoads ("ra-simple", "Number of loads added");
class RegAllocSimple : public MachineFunctionPass {
MachineFunction *MF;
@@ -79,10 +79,10 @@
/// Moves value from memory into that register
unsigned reloadVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I, unsigned VirtReg);
+ MachineBasicBlock::iterator I, unsigned VirtReg);
/// Saves reg value on the stack (maps virtual register to stack value)
- void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I,
+ void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned VirtReg, unsigned PhysReg);
};
@@ -124,39 +124,37 @@
}
unsigned RegAllocSimple::reloadVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I,
+ MachineBasicBlock::iterator I,
unsigned VirtReg) {
const TargetRegisterClass* RC = MF->getSSARegMap()->getRegClass(VirtReg);
int FrameIdx = getStackSpaceFor(VirtReg, RC);
unsigned PhysReg = getFreeReg(VirtReg);
// Add move instruction(s)
- ++NumReloaded;
+ ++NumLoads;
RegInfo->loadRegFromStackSlot(MBB, I, PhysReg, FrameIdx, RC);
return PhysReg;
}
void RegAllocSimple::spillVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I,
+ MachineBasicBlock::iterator I,
unsigned VirtReg, unsigned PhysReg) {
const TargetRegisterClass* RC = MF->getSSARegMap()->getRegClass(VirtReg);
int FrameIdx = getStackSpaceFor(VirtReg, RC);
// Add move instruction(s)
- ++NumSpilled;
+ ++NumStores;
RegInfo->storeRegToStackSlot(MBB, I, PhysReg, FrameIdx, RC);
}
void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
// loop over each instruction
- for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
+ for (MachineBasicBlock::iterator MI = MBB.begin(); MI != MBB.end(); ++MI) {
// Made to combat the incorrect allocation of r2 = add r1, r1
std::map<unsigned, unsigned> Virt2PhysRegMap;
- MachineInstr *MI = *I;
-
- RegsUsed.resize(MRegisterInfo::FirstVirtualRegister);
+ RegsUsed.resize(RegInfo->getNumRegs());
// a preliminary pass that will invalidate any registers that
// are used by the instruction (including implicit uses)
@@ -174,8 +172,8 @@
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
MachineOperand &op = MI->getOperand(i);
- if (op.isVirtualRegister()) {
- unsigned virtualReg = (unsigned) op.getAllocatedRegNum();
+ if (op.isRegister() && MRegisterInfo::isVirtualRegister(op.getReg())) {
+ unsigned virtualReg = (unsigned) op.getReg();
DEBUG(std::cerr << "op: " << op << "\n");
DEBUG(std::cerr << "\t inst[" << i << "]: ";
MI->print(std::cerr, *TM));
@@ -185,29 +183,31 @@
unsigned physReg = Virt2PhysRegMap[virtualReg];
if (physReg == 0) {
if (op.isDef()) {
- if (TM->getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) {
+ if (!TM->getInstrInfo().isTwoAddrInstr(MI->getOpcode()) || i) {
+ physReg = getFreeReg(virtualReg);
+ } else {
// must be same register number as the first operand
// This maps a = b + c into b += c, and saves b into a's spot
assert(MI->getOperand(1).isRegister() &&
- MI->getOperand(1).getAllocatedRegNum() &&
+ MI->getOperand(1).getReg() &&
MI->getOperand(1).isUse() &&
"Two address instruction invalid!");
- physReg = MI->getOperand(1).getAllocatedRegNum();
- } else {
- physReg = getFreeReg(virtualReg);
+ physReg = MI->getOperand(1).getReg();
+ spillVirtReg(MBB, next(MI), virtualReg, physReg);
+ MI->getOperand(1).setDef();
+ MI->RemoveOperand(0);
+ break; // This is the last operand to process
}
- ++I;
- spillVirtReg(MBB, I, virtualReg, physReg);
- --I;
+ spillVirtReg(MBB, next(MI), virtualReg, physReg);
} else {
- physReg = reloadVirtReg(MBB, I, virtualReg);
+ physReg = reloadVirtReg(MBB, MI, virtualReg);
Virt2PhysRegMap[virtualReg] = physReg;
}
}
MI->SetMachineOperandReg(i, physReg);
DEBUG(std::cerr << "virt: " << virtualReg <<
- ", phys: " << op.getAllocatedRegNum() << "\n");
+ ", phys: " << op.getReg() << "\n");
}
}
RegClassIdx.clear();
@@ -233,8 +233,6 @@
return true;
}
-FunctionPass *createSimpleRegisterAllocator() {
+FunctionPass *llvm::createSimpleRegisterAllocator() {
return new RegAllocSimple();
}
-
-} // End llvm namespace
Index: llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
diff -u llvm/lib/CodeGen/TwoAddressInstructionPass.cpp:1.6 llvm/lib/CodeGen/TwoAddressInstructionPass.cpp:1.6.2.1
--- llvm/lib/CodeGen/TwoAddressInstructionPass.cpp:1.6 Sun Jan 11 03:18:43 2004
+++ llvm/lib/CodeGen/TwoAddressInstructionPass.cpp Mon Mar 1 17:58:13 2004
@@ -16,53 +16,49 @@
// to:
//
// A = B
-// A = A op C
+// A op= C
+//
+// Note that if a register allocator chooses to use this pass, that it
+// has to be capable of handling the non-SSA nature of these rewritten
+// virtual registers.
+//
+// It is also worth noting that the duplicate operand of the two
+// address instruction is removed.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "twoaddrinstr"
#include "llvm/Function.h"
+#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/LiveVariables.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegInfo.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include "Support/STLExtras.h"
#include <iostream>
-
using namespace llvm;
namespace {
- class TwoAddressInstructionPass : public MachineFunctionPass
- {
- private:
- MachineFunction* mf_;
- const TargetMachine* tm_;
- const MRegisterInfo* mri_;
- LiveVariables* lv_;
+ Statistic<> numTwoAddressInstrs("twoaddressinstruction",
+ "Number of two-address instructions");
+ Statistic<> numInstrsAdded("twoaddressinstruction",
+ "Number of instructions added");
- public:
+ struct TwoAddressInstructionPass : public MachineFunctionPass
+ {
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
- private:
/// runOnMachineFunction - pass entry point
bool runOnMachineFunction(MachineFunction&);
};
RegisterPass<TwoAddressInstructionPass> X(
"twoaddressinstruction", "Two-Address instruction pass");
-
- Statistic<> numTwoAddressInstrs("twoaddressinstruction",
- "Number of two-address instructions");
- Statistic<> numInstrsAdded("twoaddressinstruction",
- "Number of instructions added");
};
const PassInfo *llvm::TwoAddressInstructionPassID = X.getPassInfo();
@@ -70,101 +66,113 @@
void TwoAddressInstructionPass::getAnalysisUsage(AnalysisUsage &AU) const
{
AU.addPreserved<LiveVariables>();
- AU.addRequired<LiveVariables>();
AU.addPreservedID(PHIEliminationID);
- AU.addRequiredID(PHIEliminationID);
MachineFunctionPass::getAnalysisUsage(AU);
}
/// runOnMachineFunction - Reduce two-address instructions to two
-/// operands
+/// operands.
///
-bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &fn) {
+bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
DEBUG(std::cerr << "Machine Function\n");
- mf_ = &fn;
- tm_ = &fn.getTarget();
- mri_ = tm_->getRegisterInfo();
- lv_ = &getAnalysis<LiveVariables>();
-
- const TargetInstrInfo& tii = tm_->getInstrInfo();
+ const TargetMachine &TM = MF.getTarget();
+ const MRegisterInfo &MRI = *TM.getRegisterInfo();
+ const TargetInstrInfo &TII = TM.getInstrInfo();
+ LiveVariables* LV = getAnalysisToUpdate<LiveVariables>();
+
+ bool MadeChange = false;
+
+ DEBUG(std::cerr << "********** REWRITING TWO-ADDR INSTRS **********\n");
+ DEBUG(std::cerr << "********** Function: "
+ << MF.getFunction()->getName() << '\n');
- for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
+ for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
mbbi != mbbe; ++mbbi) {
- for (MachineBasicBlock::iterator mii = mbbi->begin();
- mii != mbbi->end(); ++mii) {
- MachineInstr* mi = *mii;
-
+ for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end();
+ mi != me; ++mi) {
unsigned opcode = mi->getOpcode();
+
// ignore if it is not a two-address instruction
- if (!tii.isTwoAddrInstr(opcode))
+ if (!TII.isTwoAddrInstr(opcode))
continue;
++numTwoAddressInstrs;
- DEBUG(std::cerr << "\tinstruction: "; mi->print(std::cerr, *tm_));
-
- // we have nothing to do if the two operands are the same
- if (mi->getOperand(0).getAllocatedRegNum() ==
- mi->getOperand(1).getAllocatedRegNum())
- continue;
+ DEBUG(std::cerr << '\t'; mi->print(std::cerr, TM));
assert(mi->getOperand(1).isRegister() &&
- mi->getOperand(1).getAllocatedRegNum() &&
+ mi->getOperand(1).getReg() &&
mi->getOperand(1).isUse() &&
"two address instruction invalid");
- // rewrite:
- // a = b op c
- // to:
- // a = b
- // a = a op c
- unsigned regA = mi->getOperand(0).getAllocatedRegNum();
- unsigned regB = mi->getOperand(1).getAllocatedRegNum();
-
- assert(regA >= MRegisterInfo::FirstVirtualRegister &&
- regB >= MRegisterInfo::FirstVirtualRegister &&
- "cannot update physical register live information");
-
- // first make sure we do not have a use of a in the
- // instruction (a = b + a for example) because our
- // transofrmation will not work. This should never occur
- // because of SSA.
- for (unsigned i = 1; i < mi->getNumOperands(); ++i) {
- assert(!mi->getOperand(i).isRegister() ||
- mi->getOperand(i).getAllocatedRegNum() != (int)regA);
+ // if the two operands are the same we just remove the use
+ // and mark the def as def&use
+ if (mi->getOperand(0).getReg() ==
+ mi->getOperand(1).getReg()) {
}
+ else {
+ MadeChange = true;
- const TargetRegisterClass* rc =
- mf_->getSSARegMap()->getRegClass(regA);
- numInstrsAdded += mri_->copyRegToReg(*mbbi, mii, regA, regB, rc);
-
- MachineInstr* prevMi = *(mii - 1);
- DEBUG(std::cerr << "\t\tadded instruction: ";
- prevMi->print(std::cerr, *tm_));
-
- // update live variables for regA
- LiveVariables::VarInfo& varInfo = lv_->getVarInfo(regA);
- varInfo.DefInst = prevMi;
-
- // update live variables for regB
- if (lv_->removeVirtualRegisterKilled(regB, &*mbbi, mi))
- lv_->addVirtualRegisterKilled(regB, &*mbbi, prevMi);
-
- if (lv_->removeVirtualRegisterDead(regB, &*mbbi, mi))
- lv_->addVirtualRegisterDead(regB, &*mbbi, prevMi);
-
- // replace all occurences of regB with regA
- for (unsigned i = 1; i < mi->getNumOperands(); ++i) {
- if (mi->getOperand(i).isRegister() &&
- mi->getOperand(i).getReg() == regB)
- mi->SetMachineOperandReg(i, regA);
+ // rewrite:
+ // a = b op c
+ // to:
+ // a = b
+ // a = a op c
+ unsigned regA = mi->getOperand(0).getReg();
+ unsigned regB = mi->getOperand(1).getReg();
+
+ assert(MRegisterInfo::isVirtualRegister(regA) &&
+ MRegisterInfo::isVirtualRegister(regB) &&
+ "cannot update physical register live information");
+
+ // first make sure we do not have a use of a in the
+ // instruction (a = b + a for example) because our
+ // transformation will not work. This should never occur
+ // because we are in SSA form.
+ for (unsigned i = 1; i != mi->getNumOperands(); ++i)
+ assert(!mi->getOperand(i).isRegister() ||
+ mi->getOperand(i).getReg() != regA);
+
+ const TargetRegisterClass* rc =
+ MF.getSSARegMap()->getRegClass(regA);
+ unsigned Added = MRI.copyRegToReg(*mbbi, mi, regA, regB, rc);
+ numInstrsAdded += Added;
+
+ MachineBasicBlock::iterator prevMi = prior(mi);
+ DEBUG(std::cerr << "\t\tprepend:\t";
+ prevMi->print(std::cerr, TM));
+
+ if (LV) {
+ // update live variables for regA
+ assert(Added == 1 &&
+ "Cannot handle multi-instruction copies yet!");
+ LiveVariables::VarInfo& varInfo = LV->getVarInfo(regA);
+ varInfo.DefInst = prevMi;
+
+ // update live variables for regB
+ if (LV->removeVirtualRegisterKilled(regB, &*mbbi, mi))
+ LV->addVirtualRegisterKilled(regB, &*mbbi, prevMi);
+
+ if (LV->removeVirtualRegisterDead(regB, &*mbbi, mi))
+ LV->addVirtualRegisterDead(regB, &*mbbi, prevMi);
+ }
+
+ // replace all occurences of regB with regA
+ for (unsigned i = 1, e = mi->getNumOperands(); i != e; ++i) {
+ if (mi->getOperand(i).isRegister() &&
+ mi->getOperand(i).getReg() == regB)
+ mi->SetMachineOperandReg(i, regA);
+ }
}
- DEBUG(std::cerr << "\t\tmodified original to: ";
- mi->print(std::cerr, *tm_));
- assert(mi->getOperand(0).getAllocatedRegNum() ==
- mi->getOperand(1).getAllocatedRegNum());
+
+ assert(mi->getOperand(0).isDef());
+ mi->getOperand(0).setUse();
+ mi->RemoveOperand(1);
+
+ DEBUG(std::cerr << "\t\trewrite to:\t";
+ mi->print(std::cerr, TM));
}
}
- return numInstrsAdded != 0;
+ return MadeChange;
}
More information about the llvm-commits
mailing list