Skip to content

Commit 8280e25

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 7c09f12 commit 8280e25

File tree

7 files changed

+1551
-711
lines changed

7 files changed

+1551
-711
lines changed

llvm/lib/Target/M68k/M68kInstrData.td

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;
372372
/// | EFFECTIVE ADDRESS
373373
/// 0 1 0 0 0 1 0 0 1 1 | MODE | REG
374374
/// --------------------------------------------------
375-
let Defs = [CCR] in {
376375
class MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
377376
: MxInst<(outs CCRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {
378377
let Inst = (ascend
@@ -383,7 +382,6 @@ class MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
383382

384383
class MxMoveToCCRPseudo<MxOperand MEMOp>
385384
: MxPseudo<(outs CCRC:$dst), (ins MEMOp:$src)>;
386-
} // let Defs = [CCR]
387385

388386
let mayLoad = 1 in
389387
foreach AM = MxMoveSupportedAMs in {
@@ -403,7 +401,6 @@ def MOV8cd : MxMoveToCCRPseudo<MxOp8AddrMode_d.Op>;
403401
/// | EFFECTIVE ADDRESS
404402
/// 0 1 0 0 0 0 1 0 1 1 | MODE | REG
405403
/// --------------------------------------------------
406-
let Uses = [CCR] in {
407404
class MxMoveFromCCR_R
408405
: MxInst<(outs MxDRD16:$dst), (ins CCRC:$src), "move.w\t$src, $dst", []>,
409406
Requires<[ AtLeastM68010 ]> {
@@ -423,7 +420,6 @@ class MxMoveFromCCRPseudo<MxOperand MEMOp>
423420
: MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>;
424421
class MxMoveFromCCR_RPseudo<MxOperand MEMOp>
425422
: MxPseudo<(outs MEMOp:$dst), (ins CCRC:$src)>;
426-
} // let Uses = [CCR]
427423

428424
let mayStore = 1 in
429425
foreach AM = MxMoveSupportedAMs in {
@@ -445,15 +441,13 @@ def MOV8dc : MxMoveFromCCR_RPseudo<MxOp8AddrMode_d.Op>;
445441
/// | EFFECTIVE ADDRESS
446442
/// 0 1 0 0 0 1 1 0 1 1 | MODE | REG
447443
/// --------------------------------------------------
448-
let Defs = [SR] in {
449444
class MxMoveToSR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
450445
: MxInst<(outs SRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {
451446
let Inst = (ascend
452447
(descend 0b0100011011, SRC_ENC.EA),
453448
SRC_ENC.Supplement
454449
);
455450
}
456-
} // let Defs = [SR]
457451

458452
let mayLoad = 1 in
459453
foreach AM = MxMoveSupportedAMs in {
@@ -470,22 +464,20 @@ def MOV16sd : MxMoveToSR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>;
470464
/// | EFFECTIVE ADDRESS
471465
/// 0 1 0 0 0 0 0 0 1 1 | MODE | REG
472466
/// --------------------------------------------------
473-
let Uses = [SR] in {
474467
class MxMoveFromSR_R
475468
: MxInst<(outs MxDRD16:$dst), (ins SRC:$src), "move.w\t$src, $dst", []>,
476-
Requires<[ AtLeastM68010 ]> {
469+
Requires<[ IsM68000 ]> {
477470
let Inst = (descend 0b0100000011, MxEncAddrMode_d<"dst">.EA);
478471
}
479472

480473
class MxMoveFromSR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>
481474
: MxInst<(outs), (ins MEMOp:$dst, SRC:$src), "move.w\t$src, $dst", []>,
482-
Requires<[ AtLeastM68010 ]> {
475+
Requires<[ IsM68000 ]> {
483476
let Inst = (ascend
484477
(descend 0b0100000011, DST_ENC.EA),
485478
DST_ENC.Supplement
486479
);
487480
}
488-
} // let Uses = [SR]
489481

490482
let mayStore = 1 in
491483
foreach AM = MxMoveSupportedAMs in {

llvm/lib/Target/M68k/M68kInstrInfo.cpp

Lines changed: 68 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,69 @@ 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+
unsigned CCRSrcReg = STI.isM68000() ? M68k::SR : M68k::CCR;
772+
773+
// Get the live registers right before the COPY instruction. If CCR is
774+
// live, the MOVE is going to kill it, so we will need to preserve it.
775+
LiveRegUnits UsedRegs(RI);
776+
UsedRegs.addLiveOuts(MBB);
777+
auto InstUpToI = MBB.end();
778+
while (InstUpToI != MI) {
779+
UsedRegs.stepBackward(*--InstUpToI);
780+
}
781+
782+
if (SrcReg == M68k::CCR) {
783+
BuildMI(MBB, MI, DL, get(Opc), DstReg).addReg(CCRSrcReg);
784+
return;
785+
}
786+
if (DstReg == M68k::CCR) {
787+
BuildMI(MBB, MI, DL, get(Opc), M68k::CCR)
788+
.addReg(SrcReg, getKillRegState(KillSrc));
789+
return;
790+
}
791+
if (UsedRegs.available(M68k::CCR)) {
780792
BuildMI(MBB, MI, DL, get(Opc), DstReg)
781-
.addReg(SrcReg, getKillRegState(KillSrc));
793+
.addReg(SrcReg, getKillRegState(KillSrc));
782794
return;
783795
}
784796

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

790827
namespace {

llvm/lib/Target/M68k/M68kInstrInfo.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,9 @@ def IsPIC : Predicate<"TM.isPositionIndependent()">;
465465
def IsNotPIC : Predicate<"!TM.isPositionIndependent()">;
466466

467467
// ISA versions
468+
def IsM68000 : Predicate<"Subtarget->isM68000()">,
469+
AssemblerPredicate<(all_of FeatureISA00)>;
470+
468471
foreach i = [0,1,2,4,6] in
469472
def AtLeastM680 # i # "0" : Predicate<"Subtarget->atLeastM680"#i#"0()">,
470473
AssemblerPredicate<(all_of

llvm/lib/Target/M68k/M68kRegisterInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class MxPseudoReg<string N, list<Register> SUBREGS = [], list<SubRegIndex> SUBID
8787
: MxReg<N, 0, SUBREGS, SUBIDX>;
8888

8989
def CCR : MxPseudoReg<"ccr">;
90-
def SR : MxPseudoReg<"sr">;
90+
def SR : MxPseudoReg<"sr", [CCR], [MxSubRegIndex8Lo]>;
9191

9292
def PC : MxPseudoReg<"pc">;
9393

llvm/lib/Target/M68k/M68kSubtarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class M68kSubtarget : public M68kGenSubtargetInfo {
8282
/// of function is auto generated by tblgen.
8383
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
8484

85+
bool isM68000() const { return SubtargetKind == M00; }
8586
bool atLeastM68000() const { return SubtargetKind >= M00; }
8687
bool atLeastM68010() const { return SubtargetKind >= M10; }
8788
bool atLeastM68020() const { return SubtargetKind >= M20; }

0 commit comments

Comments
 (0)