You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The failing test case comes from the libcxx testsuite. Apologies for the big testcase but I didn't manage to
reduce it further using bugpoint without introducing unpleasant "undefs" everywhere.
The value of R2 is still used however has been clobbered durng the spill.
What I see is that the current algorithm in scavengeFrameVirtualRegsInBlock
loops from the last to the first instruction, but if an instruction only reads
a virtual register and does not write it, then this instruction is handled in
the next iteration (so the iteration of the previous instruction).
unsigned InitialNumVirtRegs = MRI.getNumVirtRegs();
bool NextInstructionReadsVReg = false;
for (MachineBasicBlock::iterator I = MBB.end(); I != MBB.begin(); ) {
--I;
// Move RegScavenger to the position between *I and *std::next(I).
RS.backward(I);
// Look for unassigned vregs in the uses of *std::next(I).
if (NextInstructionReadsVReg) {
MachineBasicBlock::iterator N = std::next(I);
const MachineInstr &NMI = *N;
for (const MachineOperand &MO : NMI.operands()) {
if (!MO.isReg())
continue;
unsigned Reg = MO.getReg();
// We only care about virtual registers and ignore virtual registers
// created by the target callbacks in the process (those will be handled
// in a scavenging round).
if (!TargetRegisterInfo::isVirtualRegister(Reg) ||
TargetRegisterInfo::virtReg2Index(Reg) >= InitialNumVirtRegs)
continue;
if (!MO.readsReg())
continue;
unsigned SReg = scavengeVReg(MRI, RS, Reg, true); // <-- (C)
N->addRegisterKilled(SReg, &TRI, false);
RS.setRegUsed(SReg);
}
}
... rest of the loop ...
}
So in my testcase when I == (A), given that it only reads a vreg but does not
write it, it is handled in the next iteration. This is, when I == (B) in which
case N == (A). Then because of RS.backward(I) at the beginning of the loop,
RS.MBBI points at (B) so scavengeVReg will start from (B) without
checking anything of (A).
but I'm pretty sure this is wrong (and also makes other tests fail). So I'm a
bit puzzled at this point what is the reason why the RegScavenger thinks that
R2 is an eligible register at this point. It looks to me that not considering
(A) might be the cause but then this problem could have happened in other parts
of that basic block that expose similar patterns.
Kind regards.
The text was updated successfully, but these errors were encountered:
I am trying to reproduce this. I added MF.dump() at the beginning of llvm::scavengeFrameVirtualRegs() to get a dump immediately before scavenging where the vregs to scavenge are still around.
I could not find any block in the dump that looks similar to the snippet you showed. BB#42 ends up being a short blocks that looks nothing like it and I couldn't find any similar code around. This was on todays llvm r307338 running llc without any additional flags on the file. Do I need additional flags is it just a different version?
Extended Description
This bug happens in Cortex-M0 after https://reviews.llvm.org/D21885 and none of the follow-ups seem to have fixed it.
The failing test case comes from the libcxx testsuite. Apologies for the big testcase but I didn't manage to
reduce it further using bugpoint without introducing unpleasant "undefs" everywhere.
clang -S -o test.s -mcpu=cortex-m0 --target=arm-arm-none-eabi iterator.pass.bad.ll
The issue is that, at the point the RegisterScavenger is run, we have a very big basic block, number 47.
In which the phyisical register %R2 has a very long live range as it is defined
very early in the function.
Right before the Register scavenging there is this sequence if instructions in that same basic block #47
After the register scavenger, though, R2 is spilled (R12 is a scratch register in ARM).
The value of R2 is still used however has been clobbered durng the spill.
What I see is that the current algorithm in scavengeFrameVirtualRegsInBlock
loops from the last to the first instruction, but if an instruction only reads
a virtual register and does not write it, then this instruction is handled in
the next iteration (so the iteration of the previous instruction).
static bool scavengeFrameVirtualRegsInBlock(MachineRegisterInfo &MRI,
RegScavenger &RS,
MachineBasicBlock &MBB) {
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
RS.enterBasicBlockEnd(MBB);
unsigned InitialNumVirtRegs = MRI.getNumVirtRegs();
bool NextInstructionReadsVReg = false;
for (MachineBasicBlock::iterator I = MBB.end(); I != MBB.begin(); ) {
--I;
// Move RegScavenger to the position between *I and *std::next(I).
RS.backward(I);
}
So in my testcase when I == (A), given that it only reads a vreg but does not
write it, it is handled in the next iteration. This is, when I == (B) in which
case N == (A). Then because of RS.backward(I) at the beginning of the loop,
RS.MBBI points at (B) so scavengeVReg will start from (B) without
checking anything of (A).
I made a quick experiment replacing (C) with
RS.skipTo(N);
unsigned SReg = scavengeVReg(MRI, RS, Reg, true);
but I'm pretty sure this is wrong (and also makes other tests fail). So I'm a
bit puzzled at this point what is the reason why the RegScavenger thinks that
R2 is an eligible register at this point. It looks to me that not considering
(A) might be the cause but then this problem could have happened in other parts
of that basic block that expose similar patterns.
Kind regards.
The text was updated successfully, but these errors were encountered: