[llvm] [M68k] Prevent COPY instruction from killing live condition flags (PR #168485)

Dan Salvato via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 18 07:35:49 PST 2025


================
@@ -773,18 +761,71 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
       LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to CCR\n");
       llvm_unreachable("Invalid register for MOVE to CCR");
     }
-  } else if (FromSR || ToSR)
+  } else if (SrcReg == M68k::SR || DstReg == M68k::SR)
     llvm_unreachable("Cannot emit SR copy instruction");
 
-  if (Opc) {
+  if (!Opc) {
+    LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
+                      << RI.getName(DstReg) << '\n');
+    llvm_unreachable("Cannot emit physreg copy instruction");
+  }
+
+  unsigned CCRSrcReg = STI.isM68000() ? M68k::SR : M68k::CCR;
+
+  // Get the live registers right before the COPY instruction. If CCR is
+  // live, the MOVE is going to kill it, so we will need to preserve it.
+  LiveRegUnits UsedRegs(RI);
+  UsedRegs.addLiveOuts(MBB);
+  auto InstUpToI = MBB.end();
+  while (InstUpToI != MI) {
+    UsedRegs.stepBackward(*--InstUpToI);
+  }
+
+  if (SrcReg == M68k::CCR) {
+    BuildMI(MBB, MI, DL, get(Opc), DstReg).addReg(CCRSrcReg);
+    return;
+  }
+  if (DstReg == M68k::CCR) {
+    BuildMI(MBB, MI, DL, get(Opc), M68k::CCR)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+  if (UsedRegs.available(M68k::CCR)) {
     BuildMI(MBB, MI, DL, get(Opc), DstReg)
         .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 
-  LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
-                    << RI.getName(DstReg) << '\n');
-  llvm_unreachable("Cannot emit physreg copy instruction");
+  // CCR is live, so we must restore it after the copy. Prepare push/pop ops.
+  // 68000 must use MOVE from SR, 68010+ must use MOVE from CCR. In either
+  // case, MOVE to CCR masks out the upper byte.
----------------
dansalvato wrote:

Register scavenging needs to be explicitly enabled for the backend, right? I aimed for this patch to be a standalone workaround/failsafe to prevent miscompiles, while we discuss what a complete solution may entail. So, I felt that I shouldn't go out of my way to enable a feature here, in case I didn't understand what other implications it may have (and since it would impede upon the "self-retiring" nature of this patch).

https://github.com/llvm/llvm-project/pull/168485


More information about the llvm-commits mailing list