mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
- PHI elimination also eliminates implicit_def that fits into a PHI node rather than copying it.
- Be (slightly) smarter about where to place the copies. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49165 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8a50f1fcf0
commit
576a27043d
@ -21,34 +21,25 @@
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumAtomic, "Number of atomic phis lowered");
|
||||
//STATISTIC(NumSimple, "Number of simple phis lowered");
|
||||
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN PNE : public MachineFunctionPass {
|
||||
class VISIBILITY_HIDDEN PNE : public MachineFunctionPass {
|
||||
MachineRegisterInfo *MRI; // Machine register information
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
PNE() : MachineFunctionPass((intptr_t)&ID) {}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &Fn) {
|
||||
analyzePHINodes(Fn);
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
// Eliminate PHI instructions by inserting copies into predecessor blocks.
|
||||
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
||||
Changed |= EliminatePHINodes(Fn, *I);
|
||||
|
||||
VRegPHIUseCount.clear();
|
||||
return Changed;
|
||||
}
|
||||
virtual bool runOnMachineFunction(MachineFunction &Fn);
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addPreserved<LiveVariables>();
|
||||
@ -58,6 +49,12 @@ namespace {
|
||||
}
|
||||
|
||||
private:
|
||||
/// findInsertionPoint - Find a safe location to insert a move to copy
|
||||
/// source of a PHI instruction.
|
||||
MachineBasicBlock::iterator
|
||||
findInsertionPoint(MachineBasicBlock &MBB, MachineInstr *DefMI,
|
||||
unsigned DstReg, unsigned SrcReg) const;
|
||||
|
||||
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
|
||||
/// in predecessor basic blocks.
|
||||
///
|
||||
@ -77,6 +74,9 @@ namespace {
|
||||
typedef std::map<BBVRegPair, unsigned> VRegPHIUse;
|
||||
|
||||
VRegPHIUse VRegPHIUseCount;
|
||||
|
||||
// Defs of PHI sources which are implicit_def.
|
||||
SmallPtrSet<MachineInstr*, 4> ImpDefs;
|
||||
};
|
||||
|
||||
char PNE::ID = 0;
|
||||
@ -86,6 +86,32 @@ namespace {
|
||||
|
||||
const PassInfo *llvm::PHIEliminationID = X.getPassInfo();
|
||||
|
||||
bool PNE::runOnMachineFunction(MachineFunction &Fn) {
|
||||
MRI = &Fn.getRegInfo();
|
||||
|
||||
analyzePHINodes(Fn);
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
// Eliminate PHI instructions by inserting copies into predecessor blocks.
|
||||
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
||||
Changed |= EliminatePHINodes(Fn, *I);
|
||||
|
||||
// Remove dead IMPLICIT_DEF instructions.
|
||||
for (SmallPtrSet<MachineInstr*,4>::iterator I = ImpDefs.begin(),
|
||||
E = ImpDefs.end(); I != E; ++I) {
|
||||
MachineInstr *DefMI = *I;
|
||||
unsigned DefReg = DefMI->getOperand(0).getReg();
|
||||
if (MRI->use_begin(DefReg) == MRI->use_end())
|
||||
DefMI->eraseFromParent();
|
||||
}
|
||||
|
||||
ImpDefs.clear();
|
||||
VRegPHIUseCount.clear();
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
|
||||
/// predecessor basic blocks.
|
||||
///
|
||||
@ -106,15 +132,26 @@ bool PNE::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// InstructionUsesRegister - Return true if the specified machine instr has a
|
||||
/// use of the specified register.
|
||||
static bool InstructionUsesRegister(MachineInstr *MI, unsigned SrcReg) {
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
|
||||
if (MI->getOperand(i).isRegister() &&
|
||||
MI->getOperand(i).getReg() == SrcReg &&
|
||||
MI->getOperand(i).isUse())
|
||||
return true;
|
||||
return false;
|
||||
/// findInsertionPoint - Find a safe location to insert a move to copy
|
||||
/// source of a PHI instruction.
|
||||
MachineBasicBlock::iterator
|
||||
PNE::findInsertionPoint(MachineBasicBlock &MBB, MachineInstr *DefMI,
|
||||
unsigned DstReg, unsigned SrcReg) const {
|
||||
if (DefMI->getOpcode() == TargetInstrInfo::PHI ||
|
||||
DefMI->getParent() != &MBB)
|
||||
return MBB.getFirstTerminator();
|
||||
|
||||
for (MachineRegisterInfo::use_iterator I = MRI->use_begin(SrcReg),
|
||||
E = MRI->use_end(); I != E; ++I)
|
||||
if (I->getParent() == &MBB)
|
||||
return MBB.getFirstTerminator();
|
||||
for (MachineRegisterInfo::use_iterator I = MRI->use_begin(DstReg),
|
||||
E = MRI->use_end(); I != E; ++I)
|
||||
if (I->getParent() == &MBB)
|
||||
return MBB.getFirstTerminator();
|
||||
|
||||
MachineBasicBlock::iterator I = DefMI;
|
||||
return ++I;
|
||||
}
|
||||
|
||||
/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block,
|
||||
@ -179,12 +216,20 @@ void PNE::LowerAtomicPHINode(MachineBasicBlock &MBB,
|
||||
// Now loop over all of the incoming arguments, changing them to copy into
|
||||
// the IncomingReg register in the corresponding predecessor basic block.
|
||||
//
|
||||
std::set<MachineBasicBlock*> MBBsInsertedInto;
|
||||
SmallPtrSet<MachineBasicBlock*, 8> MBBsInsertedInto;
|
||||
for (int i = MPhi->getNumOperands() - 1; i >= 2; i-=2) {
|
||||
unsigned SrcReg = MPhi->getOperand(i-1).getReg();
|
||||
assert(TargetRegisterInfo::isVirtualRegister(SrcReg) &&
|
||||
"Machine PHI Operands must all be virtual registers!");
|
||||
|
||||
// If source is defined by an implicit def, there is no need to insert
|
||||
// a copy.
|
||||
MachineInstr *DefMI = MRI->getVRegDef(SrcReg);
|
||||
if (DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
|
||||
ImpDefs.insert(DefMI);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the MachineBasicBlock equivalent of the BasicBlock that is the
|
||||
// source path the PHI.
|
||||
MachineBasicBlock &opBlock = *MPhi->getOperand(i).getMBB();
|
||||
@ -192,15 +237,16 @@ void PNE::LowerAtomicPHINode(MachineBasicBlock &MBB,
|
||||
// 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
|
||||
// same basic block.
|
||||
if (!MBBsInsertedInto.insert(&opBlock).second)
|
||||
if (!MBBsInsertedInto.insert(&opBlock))
|
||||
continue; // If the copy has already been emitted, we're done.
|
||||
|
||||
// Get an iterator pointing to the first terminator in the block (or end()).
|
||||
// This is the point where we can insert a copy if we'd like to.
|
||||
MachineBasicBlock::iterator I = opBlock.getFirstTerminator();
|
||||
// Find a safe location to insert the copy, this may be the first
|
||||
// terminator in the block (or end()).
|
||||
MachineBasicBlock::iterator InsertPos =
|
||||
findInsertionPoint(opBlock, DefMI, IncomingReg, SrcReg);
|
||||
|
||||
// Insert the copy.
|
||||
TII->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC, RC);
|
||||
TII->copyRegToReg(opBlock, InsertPos, IncomingReg, SrcReg, RC, RC);
|
||||
|
||||
// Now update live variable information if we have it. Otherwise we're done
|
||||
if (!LV) continue;
|
||||
@ -290,27 +336,23 @@ void PNE::LowerAtomicPHINode(MachineBasicBlock &MBB,
|
||||
// terminator instruction at the end of the block may also use the value.
|
||||
// In this case, we should mark *it* as being the killing block, not the
|
||||
// copy.
|
||||
bool FirstTerminatorUsesValue = false;
|
||||
if (I != opBlock.end()) {
|
||||
FirstTerminatorUsesValue = InstructionUsesRegister(I, SrcReg);
|
||||
MachineBasicBlock::iterator KillInst = prior(InsertPos);
|
||||
MachineBasicBlock::iterator Term = opBlock.getFirstTerminator();
|
||||
if (Term != opBlock.end()) {
|
||||
if (Term->readsRegister(SrcReg))
|
||||
KillInst = Term;
|
||||
|
||||
// Check that no other terminators use values.
|
||||
#ifndef NDEBUG
|
||||
for (MachineBasicBlock::iterator TI = next(I); TI != opBlock.end();
|
||||
for (MachineBasicBlock::iterator TI = next(Term); TI != opBlock.end();
|
||||
++TI) {
|
||||
assert(!InstructionUsesRegister(TI, SrcReg) &&
|
||||
assert(!TI->readsRegister(SrcReg) &&
|
||||
"Terminator instructions cannot use virtual registers unless"
|
||||
"they are the first terminator in a block!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator KillInst;
|
||||
if (!FirstTerminatorUsesValue)
|
||||
KillInst = prior(I);
|
||||
else
|
||||
KillInst = I;
|
||||
|
||||
// Finally, mark it killed.
|
||||
LV->addVirtualRegisterKilled(SrcReg, KillInst);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user