mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 20:29:48 +00:00
Fix code that break critical edges for PHI uses. Watch out for multiple PHIs in different blocks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114270 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
14ac1dd2be
commit
2399786b27
@ -86,12 +86,11 @@ namespace {
|
|||||||
MachineBasicBlock *SplitCriticalEdge(MachineInstr *MI,
|
MachineBasicBlock *SplitCriticalEdge(MachineInstr *MI,
|
||||||
MachineBasicBlock *From,
|
MachineBasicBlock *From,
|
||||||
MachineBasicBlock *To,
|
MachineBasicBlock *To,
|
||||||
bool HasNonePHIUse);
|
bool AllPHIUse);
|
||||||
bool SinkInstruction(MachineInstr *MI, bool &SawStore);
|
bool SinkInstruction(MachineInstr *MI, bool &SawStore);
|
||||||
bool AllUsesDominatedByBlock(unsigned Reg, MachineBasicBlock *MBB,
|
bool AllUsesDominatedByBlock(unsigned Reg, MachineBasicBlock *MBB,
|
||||||
MachineBasicBlock *DefMBB,
|
MachineBasicBlock *DefMBB,
|
||||||
SmallPtrSet<MachineInstr*, 4> &PHIUses,
|
bool &AllPHIUse, bool &LocalUse) const;
|
||||||
bool &NonPHIUse, bool &LocalUse) const;
|
|
||||||
bool PerformTrivialForwardCoalescing(MachineInstr *MI,
|
bool PerformTrivialForwardCoalescing(MachineInstr *MI,
|
||||||
MachineBasicBlock *MBB);
|
MachineBasicBlock *MBB);
|
||||||
};
|
};
|
||||||
@ -139,42 +138,54 @@ bool
|
|||||||
MachineSinking::AllUsesDominatedByBlock(unsigned Reg,
|
MachineSinking::AllUsesDominatedByBlock(unsigned Reg,
|
||||||
MachineBasicBlock *MBB,
|
MachineBasicBlock *MBB,
|
||||||
MachineBasicBlock *DefMBB,
|
MachineBasicBlock *DefMBB,
|
||||||
SmallPtrSet<MachineInstr*, 4> &PHIUses,
|
bool &AllPHIUse, bool &LocalUse) const {
|
||||||
bool &NonPHIUse, bool &LocalUse) const {
|
|
||||||
assert(TargetRegisterInfo::isVirtualRegister(Reg) &&
|
assert(TargetRegisterInfo::isVirtualRegister(Reg) &&
|
||||||
"Only makes sense for vregs");
|
"Only makes sense for vregs");
|
||||||
|
|
||||||
|
if (MRI->use_nodbg_empty(Reg))
|
||||||
|
return true;
|
||||||
|
|
||||||
// Ignoring debug uses is necessary so debug info doesn't affect the code.
|
// Ignoring debug uses is necessary so debug info doesn't affect the code.
|
||||||
// This may leave a referencing dbg_value in the original block, before
|
// This may leave a referencing dbg_value in the original block, before
|
||||||
// the definition of the vreg. Dwarf generator handles this although the
|
// the definition of the vreg. Dwarf generator handles this although the
|
||||||
// user might not get the right info at runtime.
|
// user might not get the right info at runtime.
|
||||||
|
|
||||||
|
// PHI is in the successor BB. e.g.
|
||||||
|
// BB#1: derived from LLVM BB %bb4.preheader
|
||||||
|
// Predecessors according to CFG: BB#0
|
||||||
|
// ...
|
||||||
|
// %reg16385<def> = DEC64_32r %reg16437, %EFLAGS<imp-def,dead>
|
||||||
|
// ...
|
||||||
|
// JE_4 <BB#37>, %EFLAGS<imp-use>
|
||||||
|
// Successors according to CFG: BB#37 BB#2
|
||||||
|
//
|
||||||
|
// BB#2: derived from LLVM BB %bb.nph
|
||||||
|
// Predecessors according to CFG: BB#0 BB#1
|
||||||
|
// %reg16386<def> = PHI %reg16434, <BB#0>, %reg16385, <BB#1>
|
||||||
|
//
|
||||||
|
// Machine sink should break the critical edge first.
|
||||||
|
AllPHIUse = true;
|
||||||
|
for (MachineRegisterInfo::use_nodbg_iterator
|
||||||
|
I = MRI->use_nodbg_begin(Reg), E = MRI->use_nodbg_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
MachineInstr *UseInst = &*I;
|
||||||
|
MachineBasicBlock *UseBlock = UseInst->getParent();
|
||||||
|
if (!(UseBlock == MBB && UseInst->isPHI() &&
|
||||||
|
UseInst->getOperand(I.getOperandNo()+1).getMBB() == DefMBB)) {
|
||||||
|
AllPHIUse = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AllPHIUse)
|
||||||
|
return true;
|
||||||
|
|
||||||
for (MachineRegisterInfo::use_nodbg_iterator
|
for (MachineRegisterInfo::use_nodbg_iterator
|
||||||
I = MRI->use_nodbg_begin(Reg), E = MRI->use_nodbg_end();
|
I = MRI->use_nodbg_begin(Reg), E = MRI->use_nodbg_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
// Determine the block of the use.
|
// Determine the block of the use.
|
||||||
MachineInstr *UseInst = &*I;
|
MachineInstr *UseInst = &*I;
|
||||||
MachineBasicBlock *UseBlock = UseInst->getParent();
|
MachineBasicBlock *UseBlock = UseInst->getParent();
|
||||||
|
if (UseInst->isPHI()) {
|
||||||
bool isPHI = UseInst->isPHI();
|
|
||||||
if (isPHI)
|
|
||||||
PHIUses.insert(UseInst);
|
|
||||||
|
|
||||||
if (isPHI) {
|
|
||||||
if (SplitEdges && UseBlock == MBB)
|
|
||||||
// PHI is in the successor BB. e.g.
|
|
||||||
// BB#1: derived from LLVM BB %bb4.preheader
|
|
||||||
// Predecessors according to CFG: BB#0
|
|
||||||
// ...
|
|
||||||
// %reg16385<def> = DEC64_32r %reg16437, %EFLAGS<imp-def,dead>
|
|
||||||
// ...
|
|
||||||
// JE_4 <BB#37>, %EFLAGS<imp-use>
|
|
||||||
// Successors according to CFG: BB#37 BB#2
|
|
||||||
//
|
|
||||||
// BB#2: derived from LLVM BB %bb.nph
|
|
||||||
// Predecessors according to CFG: BB#0 BB#1
|
|
||||||
// %reg16386<def> = PHI %reg16434, <BB#0>, %reg16385, <BB#1>
|
|
||||||
//
|
|
||||||
// Machine sink should break the critical edge first.
|
|
||||||
continue;
|
|
||||||
// PHI nodes use the operand in the predecessor block, not the block with
|
// PHI nodes use the operand in the predecessor block, not the block with
|
||||||
// the PHI.
|
// the PHI.
|
||||||
UseBlock = UseInst->getOperand(I.getOperandNo()+1).getMBB();
|
UseBlock = UseInst->getOperand(I.getOperandNo()+1).getMBB();
|
||||||
@ -293,7 +304,7 @@ bool MachineSinking::isWorthBreakingCriticalEdge(MachineInstr *MI,
|
|||||||
MachineBasicBlock *MachineSinking::SplitCriticalEdge(MachineInstr *MI,
|
MachineBasicBlock *MachineSinking::SplitCriticalEdge(MachineInstr *MI,
|
||||||
MachineBasicBlock *FromBB,
|
MachineBasicBlock *FromBB,
|
||||||
MachineBasicBlock *ToBB,
|
MachineBasicBlock *ToBB,
|
||||||
bool HasNonePHIUse) {
|
bool AllPHIUse) {
|
||||||
if (!isWorthBreakingCriticalEdge(MI, FromBB, ToBB))
|
if (!isWorthBreakingCriticalEdge(MI, FromBB, ToBB))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -345,7 +356,7 @@ MachineBasicBlock *MachineSinking::SplitCriticalEdge(MachineInstr *MI,
|
|||||||
//
|
//
|
||||||
// There is no need to do this check if all the uses are PHI nodes. PHI
|
// There is no need to do this check if all the uses are PHI nodes. PHI
|
||||||
// sources are only defined on the specific predecessor edges.
|
// sources are only defined on the specific predecessor edges.
|
||||||
if (HasNonePHIUse) {
|
if (!AllPHIUse) {
|
||||||
for (MachineBasicBlock::pred_iterator PI = ToBB->pred_begin(),
|
for (MachineBasicBlock::pred_iterator PI = ToBB->pred_begin(),
|
||||||
E = ToBB->pred_end(); PI != E; ++PI) {
|
E = ToBB->pred_end(); PI != E; ++PI) {
|
||||||
if (*PI == FromBB)
|
if (*PI == FromBB)
|
||||||
@ -381,9 +392,7 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
|
|||||||
// decide.
|
// decide.
|
||||||
MachineBasicBlock *SuccToSinkTo = 0;
|
MachineBasicBlock *SuccToSinkTo = 0;
|
||||||
|
|
||||||
SmallSet<unsigned, 4> Defs;
|
bool AllPHIUse = false;
|
||||||
SmallPtrSet<MachineInstr*, 4> PHIUses;
|
|
||||||
bool HasNonPHIUse = false;
|
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
const MachineOperand &MO = MI->getOperand(i);
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
if (!MO.isReg()) continue; // Ignore non-register operands.
|
if (!MO.isReg()) continue; // Ignore non-register operands.
|
||||||
@ -418,7 +427,6 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
|
|||||||
} else {
|
} else {
|
||||||
// Virtual register uses are always safe to sink.
|
// Virtual register uses are always safe to sink.
|
||||||
if (MO.isUse()) continue;
|
if (MO.isUse()) continue;
|
||||||
Defs.insert(Reg);
|
|
||||||
|
|
||||||
// If it's not safe to move defs of the register class, then abort.
|
// If it's not safe to move defs of the register class, then abort.
|
||||||
if (!TII->isSafeToMoveRegClassDefs(MRI->getRegClass(Reg)))
|
if (!TII->isSafeToMoveRegClassDefs(MRI->getRegClass(Reg)))
|
||||||
@ -443,8 +451,8 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
|
|||||||
// If a previous operand picked a block to sink to, then this operand
|
// If a previous operand picked a block to sink to, then this operand
|
||||||
// must be sinkable to the same block.
|
// must be sinkable to the same block.
|
||||||
bool LocalUse = false;
|
bool LocalUse = false;
|
||||||
if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo, ParentBlock, PHIUses,
|
if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo, ParentBlock,
|
||||||
HasNonPHIUse, LocalUse))
|
AllPHIUse, LocalUse))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -455,8 +463,8 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
|
|||||||
for (MachineBasicBlock::succ_iterator SI = ParentBlock->succ_begin(),
|
for (MachineBasicBlock::succ_iterator SI = ParentBlock->succ_begin(),
|
||||||
E = ParentBlock->succ_end(); SI != E; ++SI) {
|
E = ParentBlock->succ_end(); SI != E; ++SI) {
|
||||||
bool LocalUse = false;
|
bool LocalUse = false;
|
||||||
if (AllUsesDominatedByBlock(Reg, *SI, ParentBlock, PHIUses,
|
if (AllUsesDominatedByBlock(Reg, *SI, ParentBlock,
|
||||||
HasNonPHIUse, LocalUse)) {
|
AllPHIUse, LocalUse)) {
|
||||||
SuccToSinkTo = *SI;
|
SuccToSinkTo = *SI;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -530,7 +538,7 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
|
|||||||
DEBUG(dbgs() << "Sinking along critical edge.\n");
|
DEBUG(dbgs() << "Sinking along critical edge.\n");
|
||||||
else {
|
else {
|
||||||
MachineBasicBlock *NewSucc =
|
MachineBasicBlock *NewSucc =
|
||||||
SplitCriticalEdge(MI, ParentBlock, SuccToSinkTo, HasNonPHIUse);
|
SplitCriticalEdge(MI, ParentBlock, SuccToSinkTo, AllPHIUse);
|
||||||
if (!NewSucc) {
|
if (!NewSucc) {
|
||||||
DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to "
|
DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to "
|
||||||
"break critical edge\n");
|
"break critical edge\n");
|
||||||
@ -546,43 +554,30 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AllPHIUse) {
|
||||||
|
if (NumSplit == SplitLimit)
|
||||||
|
return false;
|
||||||
|
MachineBasicBlock *NewSucc = SplitCriticalEdge(MI, ParentBlock,
|
||||||
|
SuccToSinkTo, AllPHIUse);
|
||||||
|
if (!NewSucc) {
|
||||||
|
DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to "
|
||||||
|
"break critical edge\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(dbgs() << " *** Splitting critical edge:"
|
||||||
|
" BB#" << ParentBlock->getNumber()
|
||||||
|
<< " -- BB#" << NewSucc->getNumber()
|
||||||
|
<< " -- BB#" << SuccToSinkTo->getNumber() << '\n');
|
||||||
|
SuccToSinkTo = NewSucc;
|
||||||
|
++NumSplit;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine where to insert into. Skip phi nodes.
|
// Determine where to insert into. Skip phi nodes.
|
||||||
MachineBasicBlock::iterator InsertPos = SuccToSinkTo->begin();
|
MachineBasicBlock::iterator InsertPos = SuccToSinkTo->begin();
|
||||||
while (InsertPos != SuccToSinkTo->end() && InsertPos->isPHI()) {
|
while (InsertPos != SuccToSinkTo->end() && InsertPos->isPHI())
|
||||||
MachineInstr *PHI = &*InsertPos;
|
|
||||||
++InsertPos;
|
++InsertPos;
|
||||||
|
|
||||||
if (SplitEdges && PHIUses.count(PHI)) {
|
|
||||||
if (NumSplit == SplitLimit)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// A PHI use is in the destination successor so we can't sink the
|
|
||||||
// instruction here. Break the critical edge first!
|
|
||||||
for (unsigned i = 1, e = PHI->getNumOperands(); i != e; i += 2) {
|
|
||||||
unsigned SrcReg = PHI->getOperand(i).getReg();
|
|
||||||
if (Defs.count(SrcReg)) {
|
|
||||||
MachineBasicBlock *SrcMBB = PHI->getOperand(i+1).getMBB();
|
|
||||||
MachineBasicBlock *NewSucc =
|
|
||||||
SplitCriticalEdge(MI, SrcMBB, SuccToSinkTo, HasNonPHIUse);
|
|
||||||
if (!NewSucc) {
|
|
||||||
DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to "
|
|
||||||
"break critical edge\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(dbgs() << " *** Splitting critical edge:"
|
|
||||||
" BB#" << SrcMBB->getNumber()
|
|
||||||
<< " -- BB#" << NewSucc->getNumber()
|
|
||||||
<< " -- BB#" << SuccToSinkTo->getNumber() << '\n');
|
|
||||||
SuccToSinkTo = NewSucc;
|
|
||||||
InsertPos = NewSucc->begin();
|
|
||||||
++NumSplit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the instruction.
|
// Move the instruction.
|
||||||
SuccToSinkTo->splice(InsertPos, ParentBlock, MI,
|
SuccToSinkTo->splice(InsertPos, ParentBlock, MI,
|
||||||
++MachineBasicBlock::iterator(MI));
|
++MachineBasicBlock::iterator(MI));
|
||||||
|
Loading…
Reference in New Issue
Block a user