forked from OSchip/llvm-project
Another rewriter bug exposed by recent coalescer changes. ReuseInfo::GetRegForReload() should make sure the "switched" register is in the desired register class. I'm surprised this hasn't caused more failures in the past.
llvm-svn: 76558
This commit is contained in:
parent
f477ac5655
commit
07a6ac6b29
|
@ -277,7 +277,8 @@ public:
|
||||||
/// GetRegForReload - We are about to emit a reload into PhysReg. If there
|
/// GetRegForReload - We are about to emit a reload into PhysReg. If there
|
||||||
/// is some other operand that is using the specified register, either pick
|
/// is some other operand that is using the specified register, either pick
|
||||||
/// a new register to use, or evict the previous reload and use this reg.
|
/// a new register to use, or evict the previous reload and use this reg.
|
||||||
unsigned GetRegForReload(unsigned PhysReg, MachineInstr *MI,
|
unsigned GetRegForReload(const TargetRegisterClass *RC, unsigned PhysReg,
|
||||||
|
MachineFunction &MF, MachineInstr *MI,
|
||||||
AvailableSpills &Spills,
|
AvailableSpills &Spills,
|
||||||
std::vector<MachineInstr*> &MaybeDeadStores,
|
std::vector<MachineInstr*> &MaybeDeadStores,
|
||||||
SmallSet<unsigned, 8> &Rejected,
|
SmallSet<unsigned, 8> &Rejected,
|
||||||
|
@ -296,15 +297,17 @@ public:
|
||||||
/// sees r1 is taken by t2, tries t2's reload register r0
|
/// sees r1 is taken by t2, tries t2's reload register r0
|
||||||
/// sees r0 is taken by t3, tries t3's reload register r1
|
/// sees r0 is taken by t3, tries t3's reload register r1
|
||||||
/// sees r1 is taken by t2, tries t2's reload register r0 ...
|
/// sees r1 is taken by t2, tries t2's reload register r0 ...
|
||||||
unsigned GetRegForReload(unsigned PhysReg, MachineInstr *MI,
|
unsigned GetRegForReload(unsigned VirtReg, unsigned PhysReg, MachineInstr *MI,
|
||||||
AvailableSpills &Spills,
|
AvailableSpills &Spills,
|
||||||
std::vector<MachineInstr*> &MaybeDeadStores,
|
std::vector<MachineInstr*> &MaybeDeadStores,
|
||||||
BitVector &RegKills,
|
BitVector &RegKills,
|
||||||
std::vector<MachineOperand*> &KillOps,
|
std::vector<MachineOperand*> &KillOps,
|
||||||
VirtRegMap &VRM) {
|
VirtRegMap &VRM) {
|
||||||
SmallSet<unsigned, 8> Rejected;
|
SmallSet<unsigned, 8> Rejected;
|
||||||
return GetRegForReload(PhysReg, MI, Spills, MaybeDeadStores, Rejected,
|
MachineFunction &MF = *MI->getParent()->getParent();
|
||||||
RegKills, KillOps, VRM);
|
const TargetRegisterClass* RC = MF.getRegInfo().getRegClass(VirtReg);
|
||||||
|
return GetRegForReload(RC, PhysReg, MF, MI, Spills, MaybeDeadStores,
|
||||||
|
Rejected, RegKills, KillOps, VRM);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -658,15 +661,17 @@ void AvailableSpills::ModifyStackSlotOrReMat(int SlotOrReMat) {
|
||||||
/// GetRegForReload - We are about to emit a reload into PhysReg. If there
|
/// GetRegForReload - We are about to emit a reload into PhysReg. If there
|
||||||
/// is some other operand that is using the specified register, either pick
|
/// is some other operand that is using the specified register, either pick
|
||||||
/// a new register to use, or evict the previous reload and use this reg.
|
/// a new register to use, or evict the previous reload and use this reg.
|
||||||
unsigned ReuseInfo::GetRegForReload(unsigned PhysReg, MachineInstr *MI,
|
unsigned ReuseInfo::GetRegForReload(const TargetRegisterClass *RC,
|
||||||
AvailableSpills &Spills,
|
unsigned PhysReg,
|
||||||
|
MachineFunction &MF,
|
||||||
|
MachineInstr *MI, AvailableSpills &Spills,
|
||||||
std::vector<MachineInstr*> &MaybeDeadStores,
|
std::vector<MachineInstr*> &MaybeDeadStores,
|
||||||
SmallSet<unsigned, 8> &Rejected,
|
SmallSet<unsigned, 8> &Rejected,
|
||||||
BitVector &RegKills,
|
BitVector &RegKills,
|
||||||
std::vector<MachineOperand*> &KillOps,
|
std::vector<MachineOperand*> &KillOps,
|
||||||
VirtRegMap &VRM) {
|
VirtRegMap &VRM) {
|
||||||
const TargetInstrInfo* TII = MI->getParent()->getParent()->getTarget()
|
const TargetInstrInfo* TII = MF.getTarget().getInstrInfo();
|
||||||
.getInstrInfo();
|
const TargetRegisterInfo *TRI = Spills.getRegInfo();
|
||||||
|
|
||||||
if (Reuses.empty()) return PhysReg; // This is most often empty.
|
if (Reuses.empty()) return PhysReg; // This is most often empty.
|
||||||
|
|
||||||
|
@ -678,18 +683,18 @@ unsigned ReuseInfo::GetRegForReload(unsigned PhysReg, MachineInstr *MI,
|
||||||
// considered and subsequently rejected because it has also been reused
|
// considered and subsequently rejected because it has also been reused
|
||||||
// by another operand.
|
// by another operand.
|
||||||
if (Op.PhysRegReused == PhysReg &&
|
if (Op.PhysRegReused == PhysReg &&
|
||||||
Rejected.count(Op.AssignedPhysReg) == 0) {
|
Rejected.count(Op.AssignedPhysReg) == 0 &&
|
||||||
|
RC->contains(Op.AssignedPhysReg)) {
|
||||||
// Yup, use the reload register that we didn't use before.
|
// Yup, use the reload register that we didn't use before.
|
||||||
unsigned NewReg = Op.AssignedPhysReg;
|
unsigned NewReg = Op.AssignedPhysReg;
|
||||||
Rejected.insert(PhysReg);
|
Rejected.insert(PhysReg);
|
||||||
return GetRegForReload(NewReg, MI, Spills, MaybeDeadStores, Rejected,
|
return GetRegForReload(RC, NewReg, MF, MI, Spills, MaybeDeadStores, Rejected,
|
||||||
RegKills, KillOps, VRM);
|
RegKills, KillOps, VRM);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, we might also have a problem if a previously reused
|
// Otherwise, we might also have a problem if a previously reused
|
||||||
// value aliases the new register. If so, codegen the previous reload
|
// value aliases the new register. If so, codegen the previous reload
|
||||||
// and use this one.
|
// and use this one.
|
||||||
unsigned PRRU = Op.PhysRegReused;
|
unsigned PRRU = Op.PhysRegReused;
|
||||||
const TargetRegisterInfo *TRI = Spills.getRegInfo();
|
|
||||||
if (TRI->areAliases(PRRU, PhysReg)) {
|
if (TRI->areAliases(PRRU, PhysReg)) {
|
||||||
// Okay, we found out that an alias of a reused register
|
// Okay, we found out that an alias of a reused register
|
||||||
// was used. This isn't good because it means we have
|
// was used. This isn't good because it means we have
|
||||||
|
@ -707,9 +712,9 @@ unsigned ReuseInfo::GetRegForReload(unsigned PhysReg, MachineInstr *MI,
|
||||||
// slot that we were supposed to in the first place. However, that
|
// slot that we were supposed to in the first place. However, that
|
||||||
// register could hold a reuse. Check to see if it conflicts or
|
// register could hold a reuse. Check to see if it conflicts or
|
||||||
// would prefer us to use a different register.
|
// would prefer us to use a different register.
|
||||||
unsigned NewPhysReg = GetRegForReload(NewOp.AssignedPhysReg,
|
unsigned NewPhysReg = GetRegForReload(RC, NewOp.AssignedPhysReg,
|
||||||
MI, Spills, MaybeDeadStores,
|
MF, MI, Spills, MaybeDeadStores,
|
||||||
Rejected, RegKills, KillOps, VRM);
|
Rejected, RegKills, KillOps, VRM);
|
||||||
|
|
||||||
MachineBasicBlock::iterator MII = MI;
|
MachineBasicBlock::iterator MII = MI;
|
||||||
if (NewOp.StackSlotOrReMat > VirtRegMap::MAX_STACK_SLOT) {
|
if (NewOp.StackSlotOrReMat > VirtRegMap::MAX_STACK_SLOT) {
|
||||||
|
@ -1352,8 +1357,6 @@ private:
|
||||||
TID.isCall() || TID.isBarrier() || TID.isReturn() ||
|
TID.isCall() || TID.isBarrier() || TID.isReturn() ||
|
||||||
TID.hasUnmodeledSideEffects())
|
TID.hasUnmodeledSideEffects())
|
||||||
return false;
|
return false;
|
||||||
if (TID.getImplicitDefs())
|
|
||||||
return false;
|
|
||||||
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
|
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
|
||||||
MachineOperand &MO = MI.getOperand(i);
|
MachineOperand &MO = MI.getOperand(i);
|
||||||
if (!MO.isReg() || !MO.getReg())
|
if (!MO.isReg() || !MO.getReg())
|
||||||
|
@ -1790,8 +1793,9 @@ private:
|
||||||
// available. If this occurs, use the register indicated by the
|
// available. If this occurs, use the register indicated by the
|
||||||
// reuser.
|
// reuser.
|
||||||
if (ReusedOperands.hasReuses())
|
if (ReusedOperands.hasReuses())
|
||||||
DesignatedReg = ReusedOperands.GetRegForReload(DesignatedReg, &MI,
|
DesignatedReg = ReusedOperands.GetRegForReload(VirtReg,
|
||||||
Spills, MaybeDeadStores, RegKills, KillOps, VRM);
|
DesignatedReg, &MI,
|
||||||
|
Spills, MaybeDeadStores, RegKills, KillOps, VRM);
|
||||||
|
|
||||||
// If the mapped designated register is actually the physreg we have
|
// If the mapped designated register is actually the physreg we have
|
||||||
// incoming, we don't need to inserted a dead copy.
|
// incoming, we don't need to inserted a dead copy.
|
||||||
|
@ -1842,8 +1846,8 @@ private:
|
||||||
// available. If this occurs, use the register indicated by the
|
// available. If this occurs, use the register indicated by the
|
||||||
// reuser.
|
// reuser.
|
||||||
if (ReusedOperands.hasReuses())
|
if (ReusedOperands.hasReuses())
|
||||||
PhysReg = ReusedOperands.GetRegForReload(PhysReg, &MI,
|
PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI,
|
||||||
Spills, MaybeDeadStores, RegKills, KillOps, VRM);
|
Spills, MaybeDeadStores, RegKills, KillOps, VRM);
|
||||||
|
|
||||||
RegInfo->setPhysRegUsed(PhysReg);
|
RegInfo->setPhysRegUsed(PhysReg);
|
||||||
ReusedOperands.markClobbered(PhysReg);
|
ReusedOperands.markClobbered(PhysReg);
|
||||||
|
@ -2157,8 +2161,8 @@ private:
|
||||||
if (ReusedOperands.isClobbered(PhysReg)) {
|
if (ReusedOperands.isClobbered(PhysReg)) {
|
||||||
// Another def has taken the assigned physreg. It must have been a
|
// Another def has taken the assigned physreg. It must have been a
|
||||||
// use&def which got it due to reuse. Undo the reuse!
|
// use&def which got it due to reuse. Undo the reuse!
|
||||||
PhysReg = ReusedOperands.GetRegForReload(PhysReg, &MI,
|
PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI,
|
||||||
Spills, MaybeDeadStores, RegKills, KillOps, VRM);
|
Spills, MaybeDeadStores, RegKills, KillOps, VRM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue