[llvm] [M68k] Emit MOV16ds for moves from CCR on 68000 (PR #171703)

Daniel Thornburgh via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 10 13:00:36 PST 2025


https://github.com/mysterymath created https://github.com/llvm/llvm-project/pull/171703

This also marks CCR as a subregister of SR, which allows the value of SR to be tracked with respect to CCR. Finally, removes the 68010 requirement from moves from SR; this is a user mode instruction on 68000.

Fixes #85686

>From 870ad3318e7d2c5f388495daa5d99995c5cd13a1 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <mysterymath at gmail.com>
Date: Mon, 24 Nov 2025 15:48:50 -0800
Subject: [PATCH] [M68k] Emit MOV16ds for moves from CCR on 68000

This also marks CCR as a subregister of SR, which allows the value of SR
to be tracked with respect to CCR. Finally, removes the 68010
requirement from moves from SR; this is a user mode instruction on
68000.

Fixes #85686
---
 llvm/lib/Target/M68k/M68kInstrData.td         |   6 +-
 llvm/lib/Target/M68k/M68kInstrInfo.cpp        |   5 +
 llvm/lib/Target/M68k/M68kRegisterInfo.td      |   2 +-
 .../CodeGen/M68k/Control/non-cmov-switch.ll   | 219 ++++++++++++------
 4 files changed, 155 insertions(+), 77 deletions(-)

diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index 053e545827a1a..9888b4c2b0633 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -464,14 +464,12 @@ def MOV16sd : MxMoveToSR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>;
 /// --------------------------------------------------
 let Uses = [SR] in {
 class MxMoveFromSR_R
-    : MxInst<(outs MxDRD16:$dst), (ins SRC:$src), "move.w\t$src, $dst", []>,
-      Requires<[ AtLeastM68010 ]> {
+    : MxInst<(outs MxDRD16:$dst), (ins SRC:$src), "move.w\t$src, $dst", []> {
   let Inst = (descend 0b0100000011, MxEncAddrMode_d<"dst">.EA);
 }
 
 class MxMoveFromSR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>
-    : MxInst<(outs), (ins MEMOp:$dst, SRC:$src), "move.w\t$src, $dst", []>,
-      Requires<[ AtLeastM68010 ]> {
+    : MxInst<(outs), (ins MEMOp:$dst, SRC:$src), "move.w\t$src, $dst", []> {
   let Inst = (ascend
     (descend 0b0100000011, DST_ENC.EA),
     DST_ENC.Supplement
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
index b50397c375ba0..c27f5dc5eab1c 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
@@ -690,6 +690,7 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                                 const DebugLoc &DL, Register DstReg,
                                 Register SrcReg, bool KillSrc,
                                 bool RenamableDest, bool RenamableSrc) const {
+  const auto &Subtarget = MBB.getParent()->getSubtarget<M68kSubtarget>();
   unsigned Opc = 0;
 
   // First deal with the normal symmetric copies.
@@ -735,6 +736,10 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 
   if (FromCCR) {
     Opc = M68k::MOV16dc;
+    if (!Subtarget.atLeastM68010()) {
+      Opc = M68k::MOV16ds;
+      SrcReg = M68k::SR;
+    }
     if (!M68k::DR8RegClass.contains(DstReg) &&
         !M68k::DR16RegClass.contains(DstReg) &&
         !M68k::DR32RegClass.contains(DstReg)) {
diff --git a/llvm/lib/Target/M68k/M68kRegisterInfo.td b/llvm/lib/Target/M68k/M68kRegisterInfo.td
index 4942636ffd529..25492c6fc9406 100644
--- a/llvm/lib/Target/M68k/M68kRegisterInfo.td
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.td
@@ -87,7 +87,7 @@ class MxPseudoReg<string N, list<Register> SUBREGS = [], list<SubRegIndex> SUBID
     : MxReg<N, 0, SUBREGS, SUBIDX>;
 
 def CCR : MxPseudoReg<"ccr">;
-def SR  : MxPseudoReg<"sr">;
+def SR  : MxPseudoReg<"sr", [CCR], [MxSubRegIndex8Lo]>;
 
 def PC  : MxPseudoReg<"pc">;
 
diff --git a/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll b/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
index 9c9033e02f48e..2ce75d380e51e 100644
--- a/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
+++ b/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
@@ -1,31 +1,57 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc < %s -mtriple=m68k-linux  -mcpu=M68020 --verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=m68k-linux  -mcpu=M68000 --verify-machineinstrs | FileCheck --check-prefix=M68000 %s
+; RUN: llc < %s -mtriple=m68k-linux  -mcpu=M68020 --verify-machineinstrs | FileCheck --check-prefix=M68020 %s
 
 define internal void @select_i32(i32 %self, ptr nonnull %value) {
-; CHECK-LABEL: select_i32:
-; CHECK:         .cfi_startproc
-; CHECK-NEXT:  ; %bb.0: ; %start
-; CHECK-NEXT:    suba.l #4, %sp
-; CHECK-NEXT:    .cfi_def_cfa_offset -8
-; CHECK-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
-; CHECK-NEXT:    cmpi.l #0, (8,%sp)
-; CHECK-NEXT:    move.w %ccr, %d2
-; CHECK-NEXT:    sne %d1
-; CHECK-NEXT:    move.l (12,%sp), %d0
-; CHECK-NEXT:    move.w %d2, %ccr
-; CHECK-NEXT:    bne .LBB0_2
-; CHECK-NEXT:  ; %bb.1: ; %start
-; CHECK-NEXT:    and.l #255, %d1
-; CHECK-NEXT:    and.l #1, %d1
-; CHECK-NEXT:    cmpi.l #0, %d1
-; CHECK-NEXT:    bne .LBB0_3
-; CHECK-NEXT:  .LBB0_2: ; %null
-; CHECK-NEXT:    suba.l %a0, %a0
-; CHECK-NEXT:    move.l %d0, (%a0)
-; CHECK-NEXT:  .LBB0_3: ; %exit
-; CHECK-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
-; CHECK-NEXT:    adda.l #4, %sp
-; CHECK-NEXT:    rts
+; M68000-LABEL: select_i32:
+; M68000:         .cfi_startproc
+; M68000-NEXT:  ; %bb.0: ; %start
+; M68000-NEXT:    suba.l #4, %sp
+; M68000-NEXT:    .cfi_def_cfa_offset -8
+; M68000-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; M68000-NEXT:    cmpi.l #0, (8,%sp)
+; M68000-NEXT:    move.w %sr, %d2
+; M68000-NEXT:    sne %d1
+; M68000-NEXT:    move.l (12,%sp), %d0
+; M68000-NEXT:    move.w %d2, %ccr
+; M68000-NEXT:    bne .LBB0_2
+; M68000-NEXT:  ; %bb.1: ; %start
+; M68000-NEXT:    and.l #255, %d1
+; M68000-NEXT:    and.l #1, %d1
+; M68000-NEXT:    cmpi.l #0, %d1
+; M68000-NEXT:    bne .LBB0_3
+; M68000-NEXT:  .LBB0_2: ; %null
+; M68000-NEXT:    suba.l %a0, %a0
+; M68000-NEXT:    move.l %d0, (%a0)
+; M68000-NEXT:  .LBB0_3: ; %exit
+; M68000-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; M68000-NEXT:    adda.l #4, %sp
+; M68000-NEXT:    rts
+;
+; M68020-LABEL: select_i32:
+; M68020:         .cfi_startproc
+; M68020-NEXT:  ; %bb.0: ; %start
+; M68020-NEXT:    suba.l #4, %sp
+; M68020-NEXT:    .cfi_def_cfa_offset -8
+; M68020-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; M68020-NEXT:    cmpi.l #0, (8,%sp)
+; M68020-NEXT:    move.w %ccr, %d2
+; M68020-NEXT:    sne %d1
+; M68020-NEXT:    move.l (12,%sp), %d0
+; M68020-NEXT:    move.w %d2, %ccr
+; M68020-NEXT:    bne .LBB0_2
+; M68020-NEXT:  ; %bb.1: ; %start
+; M68020-NEXT:    and.l #255, %d1
+; M68020-NEXT:    and.l #1, %d1
+; M68020-NEXT:    cmpi.l #0, %d1
+; M68020-NEXT:    bne .LBB0_3
+; M68020-NEXT:  .LBB0_2: ; %null
+; M68020-NEXT:    suba.l %a0, %a0
+; M68020-NEXT:    move.l %d0, (%a0)
+; M68020-NEXT:  .LBB0_3: ; %exit
+; M68020-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; M68020-NEXT:    adda.l #4, %sp
+; M68020-NEXT:    rts
 start:
   %2 = icmp eq i32 %self, 0
   %3 = select i1 %2, i32 0, i32 1
@@ -47,30 +73,55 @@ exit:                                              ; preds = %nonnull, %null
 }
 
 define internal void @select_i16(i16 %self, ptr nonnull %value) {
-; CHECK-LABEL: select_i16:
-; CHECK:         .cfi_startproc
-; CHECK-NEXT:  ; %bb.0: ; %start
-; CHECK-NEXT:    suba.l #4, %sp
-; CHECK-NEXT:    .cfi_def_cfa_offset -8
-; CHECK-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
-; CHECK-NEXT:    cmpi.w #0, (10,%sp)
-; CHECK-NEXT:    move.w %ccr, %d2
-; CHECK-NEXT:    sne %d1
-; CHECK-NEXT:    move.l (12,%sp), %d0
-; CHECK-NEXT:    move.w %d2, %ccr
-; CHECK-NEXT:    bne .LBB1_2
-; CHECK-NEXT:  ; %bb.1: ; %start
-; CHECK-NEXT:    and.l #255, %d1
-; CHECK-NEXT:    and.w #1, %d1
-; CHECK-NEXT:    cmpi.w #0, %d1
-; CHECK-NEXT:    bne .LBB1_3
-; CHECK-NEXT:  .LBB1_2: ; %null
-; CHECK-NEXT:    suba.l %a0, %a0
-; CHECK-NEXT:    move.l %d0, (%a0)
-; CHECK-NEXT:  .LBB1_3: ; %exit
-; CHECK-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
-; CHECK-NEXT:    adda.l #4, %sp
-; CHECK-NEXT:    rts
+; M68000-LABEL: select_i16:
+; M68000:         .cfi_startproc
+; M68000-NEXT:  ; %bb.0: ; %start
+; M68000-NEXT:    suba.l #4, %sp
+; M68000-NEXT:    .cfi_def_cfa_offset -8
+; M68000-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; M68000-NEXT:    cmpi.w #0, (10,%sp)
+; M68000-NEXT:    move.w %sr, %d2
+; M68000-NEXT:    sne %d1
+; M68000-NEXT:    move.l (12,%sp), %d0
+; M68000-NEXT:    move.w %d2, %ccr
+; M68000-NEXT:    bne .LBB1_2
+; M68000-NEXT:  ; %bb.1: ; %start
+; M68000-NEXT:    and.l #255, %d1
+; M68000-NEXT:    and.w #1, %d1
+; M68000-NEXT:    cmpi.w #0, %d1
+; M68000-NEXT:    bne .LBB1_3
+; M68000-NEXT:  .LBB1_2: ; %null
+; M68000-NEXT:    suba.l %a0, %a0
+; M68000-NEXT:    move.l %d0, (%a0)
+; M68000-NEXT:  .LBB1_3: ; %exit
+; M68000-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; M68000-NEXT:    adda.l #4, %sp
+; M68000-NEXT:    rts
+;
+; M68020-LABEL: select_i16:
+; M68020:         .cfi_startproc
+; M68020-NEXT:  ; %bb.0: ; %start
+; M68020-NEXT:    suba.l #4, %sp
+; M68020-NEXT:    .cfi_def_cfa_offset -8
+; M68020-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; M68020-NEXT:    cmpi.w #0, (10,%sp)
+; M68020-NEXT:    move.w %ccr, %d2
+; M68020-NEXT:    sne %d1
+; M68020-NEXT:    move.l (12,%sp), %d0
+; M68020-NEXT:    move.w %d2, %ccr
+; M68020-NEXT:    bne .LBB1_2
+; M68020-NEXT:  ; %bb.1: ; %start
+; M68020-NEXT:    and.l #255, %d1
+; M68020-NEXT:    and.w #1, %d1
+; M68020-NEXT:    cmpi.w #0, %d1
+; M68020-NEXT:    bne .LBB1_3
+; M68020-NEXT:  .LBB1_2: ; %null
+; M68020-NEXT:    suba.l %a0, %a0
+; M68020-NEXT:    move.l %d0, (%a0)
+; M68020-NEXT:  .LBB1_3: ; %exit
+; M68020-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; M68020-NEXT:    adda.l #4, %sp
+; M68020-NEXT:    rts
 start:
   %2 = icmp eq i16 %self, 0
   %3 = select i1 %2, i16 0, i16 1
@@ -92,29 +143,53 @@ exit:                                              ; preds = %nonnull, %null
 }
 
 define internal void @select_i8(i8 %self, ptr nonnull %value) {
-; CHECK-LABEL: select_i8:
-; CHECK:         .cfi_startproc
-; CHECK-NEXT:  ; %bb.0: ; %start
-; CHECK-NEXT:     suba.l #4, %sp
-; CHECK-NEXT:   .cfi_def_cfa_offset -8
-; CHECK-NEXT:   movem.l %d2, (0,%sp)                    ; 8-byte Folded Spill
-; CHECK-NEXT:   cmpi.b #0, (11,%sp)
-; CHECK-NEXT:   move.w %ccr, %d2
-; CHECK-NEXT:   sne %d1
-; CHECK-NEXT:   move.l (12,%sp), %d0
-; CHECK-NEXT:   move.w %d2, %ccr
-; CHECK-NEXT:   bne .LBB2_2
-; CHECK-NEXT:   ; %bb.1:                                ; %start
-; CHECK-NEXT:   and.b #1, %d1
-; CHECK-NEXT:   cmpi.b #0, %d1
-; CHECK-NEXT:   bne .LBB2_3
-; CHECK-NEXT:   .LBB2_2:                                ; %null
-; CHECK-NEXT:   suba.l %a0, %a0
-; CHECK-NEXT:   move.l %d0, (%a0)
-; CHECK-NEXT:   .LBB2_3:                                ; %exit
-; CHECK-NEXT:   movem.l (0,%sp), %d2                    ; 8-byte Folded Reload
-; CHECK-NEXT:   adda.l #4, %sp
-; CHECK-NEXT:   rts
+; M68000-LABEL: select_i8:
+; M68000:         .cfi_startproc
+; M68000-NEXT:  ; %bb.0: ; %start
+; M68000-NEXT:    suba.l #4, %sp
+; M68000-NEXT:    .cfi_def_cfa_offset -8
+; M68000-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; M68000-NEXT:    cmpi.b #0, (11,%sp)
+; M68000-NEXT:    move.w %sr, %d2
+; M68000-NEXT:    sne %d1
+; M68000-NEXT:    move.l (12,%sp), %d0
+; M68000-NEXT:    move.w %d2, %ccr
+; M68000-NEXT:    bne .LBB2_2
+; M68000-NEXT:  ; %bb.1: ; %start
+; M68000-NEXT:    and.b #1, %d1
+; M68000-NEXT:    cmpi.b #0, %d1
+; M68000-NEXT:    bne .LBB2_3
+; M68000-NEXT:  .LBB2_2: ; %null
+; M68000-NEXT:    suba.l %a0, %a0
+; M68000-NEXT:    move.l %d0, (%a0)
+; M68000-NEXT:  .LBB2_3: ; %exit
+; M68000-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; M68000-NEXT:    adda.l #4, %sp
+; M68000-NEXT:    rts
+;
+; M68020-LABEL: select_i8:
+; M68020:         .cfi_startproc
+; M68020-NEXT:  ; %bb.0: ; %start
+; M68020-NEXT:    suba.l #4, %sp
+; M68020-NEXT:    .cfi_def_cfa_offset -8
+; M68020-NEXT:    movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; M68020-NEXT:    cmpi.b #0, (11,%sp)
+; M68020-NEXT:    move.w %ccr, %d2
+; M68020-NEXT:    sne %d1
+; M68020-NEXT:    move.l (12,%sp), %d0
+; M68020-NEXT:    move.w %d2, %ccr
+; M68020-NEXT:    bne .LBB2_2
+; M68020-NEXT:  ; %bb.1: ; %start
+; M68020-NEXT:    and.b #1, %d1
+; M68020-NEXT:    cmpi.b #0, %d1
+; M68020-NEXT:    bne .LBB2_3
+; M68020-NEXT:  .LBB2_2: ; %null
+; M68020-NEXT:    suba.l %a0, %a0
+; M68020-NEXT:    move.l %d0, (%a0)
+; M68020-NEXT:  .LBB2_3: ; %exit
+; M68020-NEXT:    movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; M68020-NEXT:    adda.l #4, %sp
+; M68020-NEXT:    rts
 start:
   %2 = icmp eq i8 %self, 0
   %3 = select i1 %2, i8 0, i8 1



More information about the llvm-commits mailing list