mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-18 17:55:18 +00:00
Simplify RegScavenger::forward a bit more.
Verify that early clobber registers and their aliases are not used. All changes to RegsAvailable are now done as a transaction so the order of operands makes no difference. The included test case is from PR4686. It has behaviour that was dependent on the order of operands. llvm-svn: 78465
This commit is contained in:
parent
aadd8cfa2f
commit
f73b30b329
@ -162,8 +162,14 @@ private:
|
|||||||
MachineInstr *findFirstUse(MachineBasicBlock *MBB,
|
MachineInstr *findFirstUse(MachineBasicBlock *MBB,
|
||||||
MachineBasicBlock::iterator I, unsigned Reg,
|
MachineBasicBlock::iterator I, unsigned Reg,
|
||||||
unsigned &Dist);
|
unsigned &Dist);
|
||||||
|
|
||||||
|
/// Add Reg and all its sub-registers to BV.
|
||||||
|
void addRegWithSubRegs(BitVector &BV, unsigned Reg);
|
||||||
|
|
||||||
|
/// Add Reg and its aliases to BV.
|
||||||
|
void addRegWithAliases(BitVector &BV, unsigned Reg);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,13 +51,6 @@ static bool RedefinesSuperRegPart(const MachineInstr *MI, unsigned SubReg,
|
|||||||
return SeenSuperDef && SeenSuperUse;
|
return SeenSuperDef && SeenSuperUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool RedefinesSuperRegPart(const MachineInstr *MI,
|
|
||||||
const MachineOperand &MO,
|
|
||||||
const TargetRegisterInfo *TRI) {
|
|
||||||
assert(MO.isReg() && MO.isDef() && "Not a register def!");
|
|
||||||
return RedefinesSuperRegPart(MI, MO.getReg(), TRI);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RegScavenger::isSuperRegUsed(unsigned Reg) const {
|
bool RegScavenger::isSuperRegUsed(unsigned Reg) const {
|
||||||
for (const unsigned *SuperRegs = TRI->getSuperRegisters(Reg);
|
for (const unsigned *SuperRegs = TRI->getSuperRegisters(Reg);
|
||||||
unsigned SuperReg = *SuperRegs; ++SuperRegs)
|
unsigned SuperReg = *SuperRegs; ++SuperRegs)
|
||||||
@ -190,6 +183,18 @@ static bool isLiveInButUnusedBefore(unsigned Reg, MachineInstr *MI,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) {
|
||||||
|
BV.set(Reg);
|
||||||
|
for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++)
|
||||||
|
BV.set(*R);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegScavenger::addRegWithAliases(BitVector &BV, unsigned Reg) {
|
||||||
|
BV.set(Reg);
|
||||||
|
for (const unsigned *R = TRI->getAliasSet(Reg); *R; R++)
|
||||||
|
BV.set(*R);
|
||||||
|
}
|
||||||
|
|
||||||
void RegScavenger::forward() {
|
void RegScavenger::forward() {
|
||||||
// Move ptr forward.
|
// Move ptr forward.
|
||||||
if (!Tracking) {
|
if (!Tracking) {
|
||||||
@ -209,76 +214,59 @@ void RegScavenger::forward() {
|
|||||||
ScavengeRestore = NULL;
|
ScavengeRestore = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separate register operands into 3 classes: uses, defs, earlyclobbers.
|
// Find out which registers are early clobbered, killed, defined, and marked
|
||||||
SmallVector<std::pair<const MachineOperand*,unsigned>, 4> UseMOs;
|
// def-dead in this instruction.
|
||||||
SmallVector<std::pair<const MachineOperand*,unsigned>, 4> DefMOs;
|
BitVector EarlyClobberRegs(NumPhysRegs);
|
||||||
SmallVector<std::pair<const MachineOperand*,unsigned>, 4> EarlyClobberMOs;
|
BitVector KillRegs(NumPhysRegs);
|
||||||
|
BitVector DefRegs(NumPhysRegs);
|
||||||
|
BitVector DeadRegs(NumPhysRegs);
|
||||||
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() || MO.getReg() == 0 || MO.isUndef())
|
if (!MO.isReg() || MO.isUndef())
|
||||||
continue;
|
continue;
|
||||||
if (MO.isUse())
|
unsigned Reg = MO.getReg();
|
||||||
UseMOs.push_back(std::make_pair(&MO,i));
|
if (!Reg || isReserved(Reg))
|
||||||
else if (MO.isEarlyClobber())
|
continue;
|
||||||
EarlyClobberMOs.push_back(std::make_pair(&MO,i));
|
|
||||||
else {
|
if (MO.isUse()) {
|
||||||
|
// Two-address operands implicitly kill.
|
||||||
|
if (MO.isKill() || MI->isRegTiedToDefOperand(i))
|
||||||
|
addRegWithSubRegs(KillRegs, Reg);
|
||||||
|
} else {
|
||||||
assert(MO.isDef());
|
assert(MO.isDef());
|
||||||
DefMOs.push_back(std::make_pair(&MO,i));
|
if (MO.isDead())
|
||||||
|
addRegWithSubRegs(DeadRegs, Reg);
|
||||||
|
else
|
||||||
|
addRegWithSubRegs(DefRegs, Reg);
|
||||||
|
if (MO.isEarlyClobber())
|
||||||
|
addRegWithAliases(EarlyClobberRegs, Reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process uses first.
|
// Verify uses and defs.
|
||||||
BitVector KillRegs(NumPhysRegs);
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
for (unsigned i = 0, e = UseMOs.size(); i != e; ++i) {
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
const MachineOperand MO = *UseMOs[i].first;
|
if (!MO.isReg() || MO.isUndef())
|
||||||
unsigned Idx = UseMOs[i].second;
|
continue;
|
||||||
unsigned Reg = MO.getReg();
|
unsigned Reg = MO.getReg();
|
||||||
|
if (!Reg || isReserved(Reg))
|
||||||
assert(isUsed(Reg) && "Using an undefined register!");
|
continue;
|
||||||
|
if (MO.isUse()) {
|
||||||
// Two-address operands implicitly kill.
|
assert(isUsed(Reg) && "Using an undefined register!");
|
||||||
if ((MO.isKill() || MI->isRegTiedToDefOperand(Idx)) && !isReserved(Reg)) {
|
assert(!EarlyClobberRegs.test(Reg) &&
|
||||||
KillRegs.set(Reg);
|
"Using an early clobbered register!");
|
||||||
|
} else {
|
||||||
// Mark sub-registers as used.
|
assert(MO.isDef());
|
||||||
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
|
assert((KillRegs.test(Reg) || isUnused(Reg) || isSuperRegUsed(Reg) ||
|
||||||
unsigned SubReg = *SubRegs; ++SubRegs)
|
isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
|
||||||
KillRegs.set(SubReg);
|
"Re-defining a live register!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change states of all registers after all the uses are processed to guard
|
// Commit the changes.
|
||||||
// against multiple uses.
|
|
||||||
setUnused(KillRegs);
|
setUnused(KillRegs);
|
||||||
|
setUnused(DeadRegs);
|
||||||
// Process early clobber defs then process defs. We can have a early clobber
|
setUsed(DefRegs);
|
||||||
// that is dead, it should not conflict with a def that happens one "slot"
|
|
||||||
// (see InstrSlots in LiveIntervalAnalysis.h) later.
|
|
||||||
unsigned NumECs = EarlyClobberMOs.size();
|
|
||||||
unsigned NumDefs = DefMOs.size();
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = NumECs + NumDefs; i != e; ++i) {
|
|
||||||
const MachineOperand &MO = (i < NumECs)
|
|
||||||
? *EarlyClobberMOs[i].first : *DefMOs[i-NumECs].first;
|
|
||||||
unsigned Reg = MO.getReg();
|
|
||||||
if (MO.isUndef())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If it's dead upon def, then it is now free.
|
|
||||||
if (MO.isDead()) {
|
|
||||||
setUnused(Reg, MI);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if this is merely redefining part of a super-register.
|
|
||||||
if (RedefinesSuperRegPart(MI, MO, TRI))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
assert((isReserved(Reg) || isUnused(Reg) || isSuperRegUsed(Reg) ||
|
|
||||||
isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
|
|
||||||
"Re-defining a live register!");
|
|
||||||
setUsed(Reg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
|
void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
|
||||||
|
20
test/CodeGen/Thumb2/2009-08-08-ScavengerAssert.ll
Normal file
20
test/CodeGen/Thumb2/2009-08-08-ScavengerAssert.ll
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -mtriple=armv7-eabi -mattr=+vfp2
|
||||||
|
; PR4686
|
||||||
|
|
||||||
|
@g_d = external global double ; <double*> [#uses=1]
|
||||||
|
|
||||||
|
define arm_aapcscc void @foo(float %yIncr) {
|
||||||
|
entry:
|
||||||
|
br i1 undef, label %bb, label %bb4
|
||||||
|
|
||||||
|
bb: ; preds = %entry
|
||||||
|
%0 = call arm_aapcs_vfpcc float @bar() ; <float> [#uses=1]
|
||||||
|
%1 = fpext float %0 to double ; <double> [#uses=1]
|
||||||
|
store double %1, double* @g_d, align 8
|
||||||
|
br label %bb4
|
||||||
|
|
||||||
|
bb4: ; preds = %bb, %entry
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
declare arm_aapcs_vfpcc float @bar()
|
Loading…
x
Reference in New Issue
Block a user