mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-20 14:29:27 +00:00
Grab bag of minor cleanups. Export some statistics about the number of
spills and reloads emitted git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5054 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2109f502d6
commit
da7e453aac
@ -10,6 +10,7 @@
|
|||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "Support/Statistic.h"
|
#include "Support/Statistic.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
/// PhysRegClassMap - Construct a mapping of physical register numbers to their
|
/// PhysRegClassMap - Construct a mapping of physical register numbers to their
|
||||||
/// register classes.
|
/// register classes.
|
||||||
@ -36,7 +37,10 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct RegAllocSimple : public FunctionPass {
|
Statistic<> NumSpilled ("ra-simple", "Number of registers spilled");
|
||||||
|
Statistic<> NumReloaded("ra-simple", "Number of registers reloaded");
|
||||||
|
|
||||||
|
class RegAllocSimple : public FunctionPass {
|
||||||
TargetMachine &TM;
|
TargetMachine &TM;
|
||||||
MachineFunction *MF;
|
MachineFunction *MF;
|
||||||
const MRegisterInfo *RegInfo;
|
const MRegisterInfo *RegInfo;
|
||||||
@ -54,20 +58,40 @@ namespace {
|
|||||||
// Made to combat the incorrect allocation of r2 = add r1, r1
|
// Made to combat the incorrect allocation of r2 = add r1, r1
|
||||||
std::map<unsigned, unsigned> VirtReg2PhysRegMap;
|
std::map<unsigned, unsigned> VirtReg2PhysRegMap;
|
||||||
|
|
||||||
// Maps RegClass => which index we can take a register from. Since this is a
|
// RegsUsed - Keep track of what registers are currently in use.
|
||||||
// simple register allocator, when we need a register of a certain class, we
|
std::set<unsigned> RegsUsed;
|
||||||
// just take the next available one.
|
|
||||||
std::map<unsigned, unsigned> RegsUsed;
|
// RegClassIdx - Maps RegClass => which index we can take a register
|
||||||
|
// from. Since this is a simple register allocator, when we need a register
|
||||||
|
// of a certain class, we just take the next available one.
|
||||||
std::map<const TargetRegisterClass*, unsigned> RegClassIdx;
|
std::map<const TargetRegisterClass*, unsigned> RegClassIdx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
RegAllocSimple(TargetMachine &tm)
|
RegAllocSimple(TargetMachine &tm)
|
||||||
: TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) {
|
: TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) {
|
||||||
RegsUsed[RegInfo->getFramePointer()] = 1;
|
RegsUsed.insert(RegInfo->getFramePointer());
|
||||||
RegsUsed[RegInfo->getStackPointer()] = 1;
|
RegsUsed.insert(RegInfo->getStackPointer());
|
||||||
|
|
||||||
cleanupAfterFunction();
|
cleanupAfterFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool runOnFunction(Function &Fn) {
|
||||||
|
return runOnMachineFunction(MachineFunction::get(&Fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// runOnMachineFunction - Register allocate the whole function
|
||||||
|
bool runOnMachineFunction(MachineFunction &Fn);
|
||||||
|
|
||||||
|
/// AllocateBasicBlock - Register allocate the specified basic block.
|
||||||
|
void AllocateBasicBlock(MachineBasicBlock &MBB);
|
||||||
|
|
||||||
|
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
|
||||||
|
/// in predecessor basic blocks.
|
||||||
|
void EliminatePHINodes(MachineBasicBlock &MBB);
|
||||||
|
|
||||||
|
|
||||||
bool isAvailableReg(unsigned Reg) {
|
bool isAvailableReg(unsigned Reg) {
|
||||||
// assert(Reg < MRegisterInfo::FirstVirtualReg && "...");
|
// assert(Reg < MRegisterInfo::FirstVirtualReg && "...");
|
||||||
return RegsUsed.find(Reg) == RegsUsed.end();
|
return RegsUsed.find(Reg) == RegsUsed.end();
|
||||||
@ -78,8 +102,11 @@ namespace {
|
|||||||
unsigned allocateStackSpaceFor(unsigned VirtReg,
|
unsigned allocateStackSpaceFor(unsigned VirtReg,
|
||||||
const TargetRegisterClass *regClass);
|
const TargetRegisterClass *regClass);
|
||||||
|
|
||||||
/// Given size (in bytes), returns a register that is currently unused
|
/// Given a virtual register, returns a physical register that is currently
|
||||||
|
/// unused.
|
||||||
|
///
|
||||||
/// Side effect: marks that register as being used until manually cleared
|
/// Side effect: marks that register as being used until manually cleared
|
||||||
|
///
|
||||||
unsigned getFreeReg(unsigned virtualReg);
|
unsigned getFreeReg(unsigned virtualReg);
|
||||||
|
|
||||||
/// Returns all `borrowed' registers back to the free pool
|
/// Returns all `borrowed' registers back to the free pool
|
||||||
@ -91,15 +118,14 @@ namespace {
|
|||||||
///
|
///
|
||||||
void invalidatePhysRegs(const MachineInstr *MI) {
|
void invalidatePhysRegs(const MachineInstr *MI) {
|
||||||
unsigned Opcode = MI->getOpcode();
|
unsigned Opcode = MI->getOpcode();
|
||||||
const MachineInstrInfo &MII = TM.getInstrInfo();
|
const MachineInstrDescriptor &Desc = TM.getInstrInfo().get(Opcode);
|
||||||
const MachineInstrDescriptor &Desc = MII.get(Opcode);
|
|
||||||
const unsigned *regs = Desc.ImplicitUses;
|
const unsigned *regs = Desc.ImplicitUses;
|
||||||
while (*regs)
|
while (*regs)
|
||||||
RegsUsed[*regs++] = 1;
|
RegsUsed.insert(*regs++);
|
||||||
|
|
||||||
regs = Desc.ImplicitDefs;
|
regs = Desc.ImplicitDefs;
|
||||||
while (*regs)
|
while (*regs)
|
||||||
RegsUsed[*regs++] = 1;
|
RegsUsed.insert(*regs++);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanupAfterFunction() {
|
void cleanupAfterFunction() {
|
||||||
@ -123,22 +149,6 @@ namespace {
|
|||||||
MachineBasicBlock::iterator
|
MachineBasicBlock::iterator
|
||||||
savePhysRegToStack (MachineBasicBlock &MBB,
|
savePhysRegToStack (MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator I, unsigned PhysReg);
|
MachineBasicBlock::iterator I, unsigned PhysReg);
|
||||||
|
|
||||||
/// runOnFunction - Top level implementation of instruction selection for
|
|
||||||
/// the entire function.
|
|
||||||
///
|
|
||||||
bool runOnMachineFunction(MachineFunction &Fn);
|
|
||||||
|
|
||||||
/// AllocateBasicBlock - Register allocate the specified basic block.
|
|
||||||
void AllocateBasicBlock(MachineBasicBlock &MBB);
|
|
||||||
|
|
||||||
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
|
|
||||||
/// in predecessor basic blocks.
|
|
||||||
void EliminatePHINodes(MachineBasicBlock &MBB);
|
|
||||||
|
|
||||||
bool runOnFunction(Function &Fn) {
|
|
||||||
return runOnMachineFunction(MachineFunction::get(&Fn));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -182,10 +192,9 @@ unsigned RegAllocSimple::getFreeReg(unsigned virtualReg) {
|
|||||||
|
|
||||||
if (isAvailableReg(physReg))
|
if (isAvailableReg(physReg))
|
||||||
return physReg;
|
return physReg;
|
||||||
else {
|
else
|
||||||
return getFreeReg(virtualReg);
|
return getFreeReg(virtualReg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MachineBasicBlock::iterator
|
MachineBasicBlock::iterator
|
||||||
RegAllocSimple::moveUseToReg (MachineBasicBlock &MBB,
|
RegAllocSimple::moveUseToReg (MachineBasicBlock &MBB,
|
||||||
@ -199,6 +208,7 @@ RegAllocSimple::moveUseToReg (MachineBasicBlock &MBB,
|
|||||||
PhysReg = getFreeReg(VirtReg);
|
PhysReg = getFreeReg(VirtReg);
|
||||||
|
|
||||||
// Add move instruction(s)
|
// Add move instruction(s)
|
||||||
|
++NumReloaded;
|
||||||
return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg,
|
return RegInfo->loadRegOffset2Reg(MBB, I, PhysReg,
|
||||||
RegInfo->getFramePointer(),
|
RegInfo->getFramePointer(),
|
||||||
-stackOffset, regClass->getDataSize());
|
-stackOffset, regClass->getDataSize());
|
||||||
@ -215,6 +225,7 @@ RegAllocSimple::saveVirtRegToStack (MachineBasicBlock &MBB,
|
|||||||
unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass);
|
unsigned stackOffset = allocateStackSpaceFor(VirtReg, regClass);
|
||||||
|
|
||||||
// Add move instruction(s)
|
// Add move instruction(s)
|
||||||
|
++NumSpilled;
|
||||||
return RegInfo->storeReg2RegOffset(MBB, I, PhysReg,
|
return RegInfo->storeReg2RegOffset(MBB, I, PhysReg,
|
||||||
RegInfo->getFramePointer(),
|
RegInfo->getFramePointer(),
|
||||||
-stackOffset, regClass->getDataSize());
|
-stackOffset, regClass->getDataSize());
|
||||||
@ -231,6 +242,7 @@ RegAllocSimple::savePhysRegToStack (MachineBasicBlock &MBB,
|
|||||||
unsigned offset = allocateStackSpaceFor(PhysReg, regClass);
|
unsigned offset = allocateStackSpaceFor(PhysReg, regClass);
|
||||||
|
|
||||||
// Add move instruction(s)
|
// Add move instruction(s)
|
||||||
|
++NumSpilled;
|
||||||
return RegInfo->storeReg2RegOffset(MBB, I, PhysReg,
|
return RegInfo->storeReg2RegOffset(MBB, I, PhysReg,
|
||||||
RegInfo->getFramePointer(),
|
RegInfo->getFramePointer(),
|
||||||
offset, regClass->getDataSize());
|
offset, regClass->getDataSize());
|
||||||
@ -239,9 +251,11 @@ RegAllocSimple::savePhysRegToStack (MachineBasicBlock &MBB,
|
|||||||
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
|
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
|
||||||
/// predecessor basic blocks.
|
/// predecessor basic blocks.
|
||||||
void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) {
|
void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) {
|
||||||
|
const MachineInstrInfo &MII = TM.getInstrInfo();
|
||||||
|
|
||||||
while (MBB.front()->getOpcode() == 0) {
|
while (MBB.front()->getOpcode() == 0) {
|
||||||
MachineInstr *MI = MBB.front();
|
MachineInstr *MI = MBB.front();
|
||||||
// get rid of the phi
|
// Unlink the PHI node from the basic block... but don't delete the PHI
|
||||||
MBB.erase(MBB.begin());
|
MBB.erase(MBB.begin());
|
||||||
|
|
||||||
// a preliminary pass that will invalidate any registers that
|
// a preliminary pass that will invalidate any registers that
|
||||||
@ -249,13 +263,13 @@ void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) {
|
|||||||
invalidatePhysRegs(MI);
|
invalidatePhysRegs(MI);
|
||||||
|
|
||||||
DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n");
|
DEBUG(std::cerr << "num invalid regs: " << RegsUsed.size() << "\n");
|
||||||
|
|
||||||
DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n");
|
DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n");
|
||||||
MachineOperand &targetReg = MI->getOperand(0);
|
MachineOperand &targetReg = MI->getOperand(0);
|
||||||
|
|
||||||
// If it's a virtual register, allocate a physical one
|
// If it's a virtual register, allocate a physical one otherwise, just use
|
||||||
// otherwise, just use whatever register is there now
|
// whatever register is there now note: it MUST be a register -- we're
|
||||||
// note: it MUST be a register -- we're assigning to it
|
// assigning to it!
|
||||||
|
//
|
||||||
unsigned virtualReg = (unsigned) targetReg.getAllocatedRegNum();
|
unsigned virtualReg = (unsigned) targetReg.getAllocatedRegNum();
|
||||||
unsigned physReg;
|
unsigned physReg;
|
||||||
if (targetReg.isVirtualRegister()) {
|
if (targetReg.isVirtualRegister()) {
|
||||||
@ -278,7 +292,6 @@ void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) {
|
|||||||
MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock();
|
MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock();
|
||||||
MachineBasicBlock::iterator opI = opBlock.end();
|
MachineBasicBlock::iterator opI = opBlock.end();
|
||||||
MachineInstr *opMI = *--opI;
|
MachineInstr *opMI = *--opI;
|
||||||
const MachineInstrInfo &MII = TM.getInstrInfo();
|
|
||||||
|
|
||||||
// must backtrack over ALL the branches in the previous block, until no
|
// must backtrack over ALL the branches in the previous block, until no
|
||||||
// more
|
// more
|
||||||
@ -300,10 +313,9 @@ void RegAllocSimple::EliminatePHINodes(MachineBasicBlock &MBB) {
|
|||||||
} else {
|
} else {
|
||||||
// Allocate a physical register and add a move in the BB
|
// Allocate a physical register and add a move in the BB
|
||||||
unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum();
|
unsigned opVirtualReg = (unsigned) opVal.getAllocatedRegNum();
|
||||||
unsigned opPhysReg; // = getFreeReg(opVirtualReg);
|
unsigned opPhysReg;
|
||||||
opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg);
|
opI = moveUseToReg(opBlock, opI, opVirtualReg, physReg);
|
||||||
//opI = RegInfo->moveReg2Reg(opBlock, opI, physReg, opPhysReg,
|
|
||||||
// dataSize);
|
|
||||||
// Save that register value to the stack of the TARGET REG
|
// Save that register value to the stack of the TARGET REG
|
||||||
saveVirtRegToStack(opBlock, opI, virtualReg, physReg);
|
saveVirtRegToStack(opBlock, opI, virtualReg, physReg);
|
||||||
}
|
}
|
||||||
@ -334,9 +346,7 @@ void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
|
|||||||
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
|
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
|
||||||
MachineOperand &op = MI->getOperand(i);
|
MachineOperand &op = MI->getOperand(i);
|
||||||
|
|
||||||
if (op.isImmediate()) {
|
if (op.isVirtualRegister()) {
|
||||||
DEBUG(std::cerr << "const\n");
|
|
||||||
} else if (op.isVirtualRegister()) {
|
|
||||||
unsigned virtualReg = (unsigned) op.getAllocatedRegNum();
|
unsigned virtualReg = (unsigned) op.getAllocatedRegNum();
|
||||||
DEBUG(std::cerr << "op: " << op << "\n");
|
DEBUG(std::cerr << "op: " << op << "\n");
|
||||||
DEBUG(std::cerr << "\t inst[" << i << "]: ";
|
DEBUG(std::cerr << "\t inst[" << i << "]: ";
|
||||||
@ -352,7 +362,7 @@ void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
|
|||||||
if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) {
|
if (TM.getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) {
|
||||||
// must be same register number as the first operand
|
// must be same register number as the first operand
|
||||||
// This maps a = b + c into b += c, and saves b into a's spot
|
// This maps a = b + c into b += c, and saves b into a's spot
|
||||||
physReg = (unsigned) MI->getOperand(1).getAllocatedRegNum();
|
physReg = MI->getOperand(1).getAllocatedRegNum();
|
||||||
} else {
|
} else {
|
||||||
physReg = getFreeReg(virtualReg);
|
physReg = getFreeReg(virtualReg);
|
||||||
}
|
}
|
||||||
@ -375,6 +385,8 @@ void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// runOnMachineFunction - Register allocate the whole function
|
||||||
|
///
|
||||||
bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
|
bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
|
||||||
DEBUG(std::cerr << "Machine Function " << "\n");
|
DEBUG(std::cerr << "Machine Function " << "\n");
|
||||||
MF = &Fn;
|
MF = &Fn;
|
||||||
@ -393,9 +405,7 @@ bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
|
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
|
||||||
MBB != MBBe; ++MBB) {
|
MBB != MBBe; ++MBB) {
|
||||||
// check if last instruction is a RET
|
// check if last instruction is a RET
|
||||||
MachineBasicBlock::iterator I = MBB->end();
|
if (MII.isReturn(MBB->back()->getOpcode())) {
|
||||||
MachineInstr *MI = *--I;
|
|
||||||
if (MII.isReturn(MI->getOpcode())) {
|
|
||||||
// this block has a return instruction, add epilogue
|
// this block has a return instruction, add epilogue
|
||||||
RegInfo->emitEpilogue(*MBB, NumBytesAllocated);
|
RegInfo->emitEpilogue(*MBB, NumBytesAllocated);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user