Skip to content

Commit 7b19681

Browse files
committed
[M68k] Fix COPY instruction killing live condition flags
During PHI node elimination, a COPY instruction is inserted that is not known to kill condition flags until after it is lowered by `copyPhysReg()`. To mitigate this, `copyPhysReg()` now has logic to determine whether the CCR is live, and if so, will back it up and restore it after the COPY. I've only seen this occur due to PHI elimination, but if the root cause is that LLVM assumes COPY has no side-effects, then perhaps this would show up elsewhere as well. [M68k] Fix CCR edge cases in `copyPhysReg()`
1 parent d7f7e1d commit 7b19681

File tree

1 file changed

+66
-31
lines changed

1 file changed

+66
-31
lines changed

llvm/lib/Target/M68k/M68kInstrInfo.cpp

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,11 @@ bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
583583
// Replace the pseudo instruction with the real one
584584
if (IsToCCR)
585585
MIB->setDesc(get(M68k::MOV16cd));
586-
else
587-
// FIXME M68010 or later is required
586+
else if (MIB->getParent()->getParent()->getSubtarget<M68kSubtarget>()
587+
.atLeastM68010())
588588
MIB->setDesc(get(M68k::MOV16dc));
589+
else
590+
MIB->setDesc(get(M68k::MOV16ds));
589591

590592
return true;
591593
}
@@ -709,6 +711,8 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
709711
Register SrcReg, bool KillSrc,
710712
bool RenamableDest, bool RenamableSrc) const {
711713
unsigned Opc = 0;
714+
MachineFunction &MF = *MBB.getParent();
715+
const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
712716

713717
// First deal with the normal symmetric copies.
714718
if (M68k::XR32RegClass.contains(DstReg, SrcReg))
@@ -718,20 +722,13 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
718722
else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
719723
Opc = M68k::MOV8dd;
720724

721-
if (Opc) {
722-
BuildMI(MBB, MI, DL, get(Opc), DstReg)
723-
.addReg(SrcReg, getKillRegState(KillSrc));
724-
return;
725-
}
726-
727725
// Now deal with asymmetrically sized copies. The cases that follow are upcast
728726
// moves.
729727
//
730728
// NOTE
731729
// These moves are not aware of type nature of these values and thus
732730
// won't do any SExt or ZExt and upper bits will basically contain garbage.
733-
MachineInstrBuilder MIB(*MBB.getParent(), MI);
734-
if (M68k::DR8RegClass.contains(SrcReg)) {
731+
else if (M68k::DR8RegClass.contains(SrcReg)) {
735732
if (M68k::XR16RegClass.contains(DstReg))
736733
Opc = M68k::MOVXd16d8;
737734
else if (M68k::XR32RegClass.contains(DstReg))
@@ -740,29 +737,18 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
740737
M68k::XR32RegClass.contains(DstReg))
741738
Opc = M68k::MOVXd32d16;
742739

743-
if (Opc) {
744-
BuildMI(MBB, MI, DL, get(Opc), DstReg)
745-
.addReg(SrcReg, getKillRegState(KillSrc));
746-
return;
747-
}
748-
749-
bool FromCCR = SrcReg == M68k::CCR;
750-
bool FromSR = SrcReg == M68k::SR;
751-
bool ToCCR = DstReg == M68k::CCR;
752-
bool ToSR = DstReg == M68k::SR;
753-
754-
if (FromCCR) {
740+
else if (SrcReg == M68k::CCR) {
755741
if (M68k::DR8RegClass.contains(DstReg)) {
756742
Opc = M68k::MOV8dc;
757743
} else if (M68k::DR16RegClass.contains(DstReg)) {
758-
Opc = M68k::MOV16dc;
744+
Opc = STI.isM68000() ? M68k::MOV16ds : M68k::MOV16dc;
759745
} else if (M68k::DR32RegClass.contains(DstReg)) {
760-
Opc = M68k::MOV16dc;
746+
Opc = STI.isM68000() ? M68k::MOV16ds : M68k::MOV16dc;
761747
} else {
762748
LLVM_DEBUG(dbgs() << "Cannot copy CCR to " << RI.getName(DstReg) << '\n');
763749
llvm_unreachable("Invalid register for MOVE from CCR");
764750
}
765-
} else if (ToCCR) {
751+
} else if (DstReg == M68k::CCR) {
766752
if (M68k::DR8RegClass.contains(SrcReg)) {
767753
Opc = M68k::MOV8cd;
768754
} else if (M68k::DR16RegClass.contains(SrcReg)) {
@@ -773,18 +759,67 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
773759
LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to CCR\n");
774760
llvm_unreachable("Invalid register for MOVE to CCR");
775761
}
776-
} else if (FromSR || ToSR)
762+
} else if (SrcReg == M68k::SR || DstReg == M68k::SR)
777763
llvm_unreachable("Cannot emit SR copy instruction");
778764

779-
if (Opc) {
765+
if (!Opc) {
766+
LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
767+
<< RI.getName(DstReg) << '\n');
768+
llvm_unreachable("Cannot emit physreg copy instruction");
769+
}
770+
771+
// Get the live registers right before the COPY instruction. If CCR is
772+
// live, the MOVE is going to kill it, so we will need to preserve it.
773+
LiveRegUnits UsedRegs(RI);
774+
UsedRegs.addLiveOuts(MBB);
775+
auto InstUpToI = MBB.end();
776+
while (InstUpToI != MI) {
777+
UsedRegs.stepBackward(*--InstUpToI);
778+
}
779+
780+
if (SrcReg == M68k::CCR) {
781+
BuildMI(MBB, MI, DL, get(Opc), DstReg);
782+
return;
783+
}
784+
if (DstReg == M68k::CCR) {
785+
BuildMI(MBB, MI, DL, get(Opc))
786+
.addReg(SrcReg, getKillRegState(KillSrc));
787+
return;
788+
}
789+
if (UsedRegs.available(M68k::CCR)) {
780790
BuildMI(MBB, MI, DL, get(Opc), DstReg)
781-
.addReg(SrcReg, getKillRegState(KillSrc));
791+
.addReg(SrcReg, getKillRegState(KillSrc));
782792
return;
783793
}
784794

785-
LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
786-
<< RI.getName(DstReg) << '\n');
787-
llvm_unreachable("Cannot emit physreg copy instruction");
795+
// CCR is live, so we must restore it after the copy. Prepare push/pop ops.
796+
// 68000 must use MOVE from SR, 68010+ must use MOVE from CCR. In either
797+
// case, MOVE to CCR masks out the upper byte.
798+
799+
// Look for an available data register for the CCR, or push to stack if
800+
// there are none
801+
BitVector Allocatable = RI.getAllocatableSet(
802+
MF, RI.getRegClass(M68k::DR16RegClassID));
803+
for (Register Reg : Allocatable.set_bits()) {
804+
if (!RI.regsOverlap(DstReg, Reg) && (UsedRegs.available(Reg))) {
805+
unsigned CCRPushOp = STI.isM68000() ? M68k::MOV16ds : M68k::MOV16dc;
806+
unsigned CCRPopOp = M68k::MOV16cd;
807+
BuildMI(MBB, MI, DL, get(CCRPushOp), Reg);
808+
BuildMI(MBB, MI, DL, get(Opc), DstReg)
809+
.addReg(SrcReg, getKillRegState(KillSrc));
810+
BuildMI(MBB, MI, DL, get(CCRPopOp)).addReg(Reg);
811+
return;
812+
}
813+
}
814+
815+
unsigned CCRPushOp = STI.isM68000() ? M68k::MOV16es : M68k::MOV16ec;
816+
unsigned CCRPopOp = M68k::MOV16co;
817+
818+
BuildMI(MBB, MI, DL, get(CCRPushOp)).addReg(RI.getStackRegister());
819+
BuildMI(MBB, MI, DL, get(Opc), DstReg)
820+
.addReg(SrcReg, getKillRegState(KillSrc));
821+
BuildMI(MBB, MI, DL, get(CCRPopOp)).addReg(RI.getStackRegister());
822+
return;
788823
}
789824

790825
namespace {

0 commit comments

Comments
 (0)