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

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 17 22:19:52 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-m68k

Author: Dan Salvato (dansalvato)

<details>
<summary>Changes</summary>

Addresses #<!-- -->152816.

There are various cases where a COPY instruction is inserted late into MI generation, such as during PHI node elimination and in handling atomic instructions. The problem is, these COPY instructions are often placed right before conditional branches, killing the live condition flags and causing a very nasty miscompile.

This patch introduces a safeguard in `copyPhysReg()` that backs up and restores the CCR if it's found to be live at that point in the block.

This is basically a workaround, but IMO it should be considered for two reasons:

1. As-is, LLVM is generating broken code, and this specific miscompile happens quite often, so preventing it should be high priority.
2. If/When the root cause is eventually addressed, this code path (finding a live CCR in `copyPhysReg()`) would become unreachable, meaning it will effectively retire itself when it is no longer needed.

Other things to note:

- Implicit defs/uses were removed from the TableGen instructions for MOVE to/from CCR/SR, because they are set up to take CCR/SR as explicit operands.
- The CCR backup uses a register if available, and the stack if not. Also, 68000 does not have MOVE from CCR, so it instead uses MOVE from SR, which includes the CCR.
- The tests I've updated were previously producing code that suffered from the same issue of using killed condition flags. They are now producing working code, which also serves as a good example of the CCR backup/restore behavior.

---

Patch is 125.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168485.diff


7 Files Affected:

- (modified) llvm/lib/Target/M68k/M68kInstrData.td (+2-10) 
- (modified) llvm/lib/Target/M68k/M68kInstrInfo.cpp (+68-31) 
- (modified) llvm/lib/Target/M68k/M68kInstrInfo.td (+3) 
- (modified) llvm/lib/Target/M68k/M68kRegisterInfo.td (+1-1) 
- (modified) llvm/lib/Target/M68k/M68kSubtarget.h (+1) 
- (modified) llvm/test/CodeGen/M68k/Atomics/rmw.ll (+487-218) 
- (modified) llvm/test/CodeGen/M68k/CodeModel/Large/Atomics/rmw.ll (+989-451) 


``````````diff
diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index c5b7ae332822f..9bb2c5aa2c971 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -372,7 +372,6 @@ def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;
 ///                               | EFFECTIVE ADDRESS
 ///  0  1  0  0  0  1  0  0  1  1 |   MODE  |   REG
 /// --------------------------------------------------
-let Defs = [CCR] in {
 class MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
     : MxInst<(outs CCRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {
   let Inst = (ascend
@@ -383,7 +382,6 @@ class MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
 
 class MxMoveToCCRPseudo<MxOperand MEMOp>
     : MxPseudo<(outs CCRC:$dst), (ins MEMOp:$src)>;
-} // let Defs = [CCR]
 
 let mayLoad = 1 in
 foreach AM = MxMoveSupportedAMs in {
@@ -403,7 +401,6 @@ def MOV8cd  : MxMoveToCCRPseudo<MxOp8AddrMode_d.Op>;
 ///                               | EFFECTIVE ADDRESS
 ///  0  1  0  0  0  0  1  0  1  1 |   MODE  |   REG
 /// --------------------------------------------------
-let Uses = [CCR] in {
 class MxMoveFromCCR_R
     : MxInst<(outs MxDRD16:$dst), (ins CCRC:$src), "move.w\t$src, $dst", []>,
       Requires<[ AtLeastM68010 ]> {
@@ -423,7 +420,6 @@ class MxMoveFromCCRPseudo<MxOperand MEMOp>
     : MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>;
 class MxMoveFromCCR_RPseudo<MxOperand MEMOp>
     : MxPseudo<(outs MEMOp:$dst), (ins CCRC:$src)>;
-} // let Uses = [CCR]
 
 let mayStore = 1 in
 foreach AM = MxMoveSupportedAMs in {
@@ -445,7 +441,6 @@ def MOV8dc  : MxMoveFromCCR_RPseudo<MxOp8AddrMode_d.Op>;
 ///                               | EFFECTIVE ADDRESS
 ///  0  1  0  0  0  1  1  0  1  1 |   MODE  |   REG
 /// --------------------------------------------------
-let Defs = [SR] in {
 class MxMoveToSR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
     : MxInst<(outs SRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> {
   let Inst = (ascend
@@ -453,7 +448,6 @@ class MxMoveToSR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
     SRC_ENC.Supplement
   );
 }
-} // let Defs = [SR]
 
 let mayLoad = 1 in
 foreach AM = MxMoveSupportedAMs in {
@@ -470,22 +464,20 @@ def MOV16sd : MxMoveToSR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>;
 ///                               | EFFECTIVE ADDRESS
 ///  0  1  0  0  0  0  0  0  1  1 |   MODE  |   REG
 /// --------------------------------------------------
-let Uses = [SR] in {
 class MxMoveFromSR_R
     : MxInst<(outs MxDRD16:$dst), (ins SRC:$src), "move.w\t$src, $dst", []>,
-      Requires<[ AtLeastM68010 ]> {
+      Requires<[ IsM68000 ]> {
   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 ]> {
+      Requires<[ IsM68000 ]> {
   let Inst = (ascend
     (descend 0b0100000011, DST_ENC.EA),
     DST_ENC.Supplement
   );
 }
-} // let Uses = [SR]
 
 let mayStore = 1 in
 foreach AM = MxMoveSupportedAMs in {
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
index 91077ff5961a4..40f2d9b37fa5f 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
@@ -583,9 +583,11 @@ bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
   // Replace the pseudo instruction with the real one
   if (IsToCCR)
     MIB->setDesc(get(M68k::MOV16cd));
-  else
-    // FIXME M68010 or later is required
+  else if (MIB->getParent()->getParent()->getSubtarget<M68kSubtarget>()
+            .atLeastM68010())
     MIB->setDesc(get(M68k::MOV16dc));
+  else
+    MIB->setDesc(get(M68k::MOV16ds));
 
   return true;
 }
@@ -709,6 +711,8 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                                 Register SrcReg, bool KillSrc,
                                 bool RenamableDest, bool RenamableSrc) const {
   unsigned Opc = 0;
+  MachineFunction &MF = *MBB.getParent();
+  const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
 
   // First deal with the normal symmetric copies.
   if (M68k::XR32RegClass.contains(DstReg, SrcReg))
@@ -718,20 +722,13 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
     Opc = M68k::MOV8dd;
 
-  if (Opc) {
-    BuildMI(MBB, MI, DL, get(Opc), DstReg)
-        .addReg(SrcReg, getKillRegState(KillSrc));
-    return;
-  }
-
   // Now deal with asymmetrically sized copies. The cases that follow are upcast
   // moves.
   //
   // NOTE
   // These moves are not aware of type nature of these values and thus
   // won't do any SExt or ZExt and upper bits will basically contain garbage.
-  MachineInstrBuilder MIB(*MBB.getParent(), MI);
-  if (M68k::DR8RegClass.contains(SrcReg)) {
+  else if (M68k::DR8RegClass.contains(SrcReg)) {
     if (M68k::XR16RegClass.contains(DstReg))
       Opc = M68k::MOVXd16d8;
     else if (M68k::XR32RegClass.contains(DstReg))
@@ -740,29 +737,18 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
              M68k::XR32RegClass.contains(DstReg))
     Opc = M68k::MOVXd32d16;
 
-  if (Opc) {
-    BuildMI(MBB, MI, DL, get(Opc), DstReg)
-        .addReg(SrcReg, getKillRegState(KillSrc));
-    return;
-  }
-
-  bool FromCCR = SrcReg == M68k::CCR;
-  bool FromSR = SrcReg == M68k::SR;
-  bool ToCCR = DstReg == M68k::CCR;
-  bool ToSR = DstReg == M68k::SR;
-
-  if (FromCCR) {
+  else if (SrcReg == M68k::CCR) {
     if (M68k::DR8RegClass.contains(DstReg)) {
       Opc = M68k::MOV8dc;
     } else if (M68k::DR16RegClass.contains(DstReg)) {
-      Opc = M68k::MOV16dc;
+      Opc = STI.isM68000() ? M68k::MOV16ds : M68k::MOV16dc;
     } else if (M68k::DR32RegClass.contains(DstReg)) {
-      Opc = M68k::MOV16dc;
+      Opc = STI.isM68000() ? M68k::MOV16ds : M68k::MOV16dc;
     } else {
       LLVM_DEBUG(dbgs() << "Cannot copy CCR to " << RI.getName(DstReg) << '\n');
       llvm_unreachable("Invalid register for MOVE from CCR");
     }
-  } else if (ToCCR) {
+  } else if (DstReg == M68k::CCR) {
     if (M68k::DR8RegClass.contains(SrcReg)) {
       Opc = M68k::MOV8cd;
     } else if (M68k::DR16RegClass.contains(SrcReg)) {
@@ -773,18 +759,69 @@ 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));
+      .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.
+
+  // Look for an available data register for the CCR, or push to stack if
+  // there are none
+  BitVector Allocatable = RI.getAllocatableSet(
+      MF, RI.getRegClass(M68k::DR16RegClassID));
+  for (Register Reg : Allocatable.set_bits()) {
+    if (!RI.regsOverlap(DstReg, Reg) && (UsedRegs.available(Reg))) {
+      unsigned CCRPushOp = STI.isM68000() ? M68k::MOV16ds : M68k::MOV16dc;
+      unsigned CCRPopOp = M68k::MOV16cd;
+      BuildMI(MBB, MI, DL, get(CCRPushOp), Reg).addReg(CCRSrcReg);
+      BuildMI(MBB, MI, DL, get(Opc), DstReg)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+      BuildMI(MBB, MI, DL, get(CCRPopOp), M68k::CCR).addReg(Reg);
+      return;
+    }
+  }
+
+  unsigned CCRPushOp = STI.isM68000() ? M68k::MOV16es : M68k::MOV16ec;
+  unsigned CCRPopOp = M68k::MOV16co;
+
+  BuildMI(MBB, MI, DL, get(CCRPushOp)).addReg(RI.getStackRegister()).addReg(CCRSrcReg);
+  BuildMI(MBB, MI, DL, get(Opc), DstReg)
+    .addReg(SrcReg, getKillRegState(KillSrc));
+  BuildMI(MBB, MI, DL, get(CCRPopOp), M68k::CCR).addReg(RI.getStackRegister());
+  return;
 }
 
 namespace {
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.td b/llvm/lib/Target/M68k/M68kInstrInfo.td
index 1200c493f9fca..3aa4826ff4e47 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.td
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.td
@@ -465,6 +465,9 @@ def IsPIC        : Predicate<"TM.isPositionIndependent()">;
 def IsNotPIC     : Predicate<"!TM.isPositionIndependent()">;
 
 // ISA versions
+def IsM68000 : Predicate<"Subtarget->isM68000()">,
+                            AssemblerPredicate<(all_of FeatureISA00)>;
+
 foreach i = [0,1,2,4,6] in
 def AtLeastM680 # i # "0" : Predicate<"Subtarget->atLeastM680"#i#"0()">,
                             AssemblerPredicate<(all_of
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/lib/Target/M68k/M68kSubtarget.h b/llvm/lib/Target/M68k/M68kSubtarget.h
index 4f9685814d9a9..0a46f3b8e371f 100644
--- a/llvm/lib/Target/M68k/M68kSubtarget.h
+++ b/llvm/lib/Target/M68k/M68kSubtarget.h
@@ -82,6 +82,7 @@ class M68kSubtarget : public M68kGenSubtargetInfo {
   /// of function is auto generated by tblgen.
   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
 
+  bool isM68000() const { return SubtargetKind == M00; }
   bool atLeastM68000() const { return SubtargetKind >= M00; }
   bool atLeastM68010() const { return SubtargetKind >= M10; }
   bool atLeastM68020() const { return SubtargetKind >= M20; }
diff --git a/llvm/test/CodeGen/M68k/Atomics/rmw.ll b/llvm/test/CodeGen/M68k/Atomics/rmw.ll
index 71ab4326cfe7d..8b304162df630 100644
--- a/llvm/test/CodeGen/M68k/Atomics/rmw.ll
+++ b/llvm/test/CodeGen/M68k/Atomics/rmw.ll
@@ -1,23 +1,36 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc %s -o - -mtriple=m68k -mcpu=M68000 -verify-machineinstrs | FileCheck %s --check-prefix=NO-ATOMIC
-; RUN: llc %s -o - -mtriple=m68k -mcpu=M68010 -verify-machineinstrs | FileCheck %s --check-prefix=NO-ATOMIC
+; RUN: llc %s -o - -mtriple=m68k -mcpu=M68000 -verify-machineinstrs | FileCheck %s --check-prefix=NO-ATOMIC-000
+; RUN: llc %s -o - -mtriple=m68k -mcpu=M68010 -verify-machineinstrs | FileCheck %s --check-prefix=NO-ATOMIC-010
 ; RUN: llc %s -o - -mtriple=m68k -mcpu=M68020 -verify-machineinstrs | FileCheck %s --check-prefix=ATOMIC
 ; RUN: llc %s -o - -mtriple=m68k -mcpu=M68030 -verify-machineinstrs | FileCheck %s --check-prefix=ATOMIC
 ; RUN: llc %s -o - -mtriple=m68k -mcpu=M68040 -verify-machineinstrs | FileCheck %s --check-prefix=ATOMIC
 
 define i8 @atomicrmw_add_i8(i8 %val, ptr %ptr) {
-; NO-ATOMIC-LABEL: atomicrmw_add_i8:
-; NO-ATOMIC:         .cfi_startproc
-; NO-ATOMIC-NEXT:  ; %bb.0:
-; NO-ATOMIC-NEXT:    suba.l #12, %sp
-; NO-ATOMIC-NEXT:    .cfi_def_cfa_offset -16
-; NO-ATOMIC-NEXT:    move.b (19,%sp), %d0
-; NO-ATOMIC-NEXT:    and.l #255, %d0
-; NO-ATOMIC-NEXT:    move.l %d0, (4,%sp)
-; NO-ATOMIC-NEXT:    move.l (20,%sp), (%sp)
-; NO-ATOMIC-NEXT:    jsr __sync_fetch_and_add_1
-; NO-ATOMIC-NEXT:    adda.l #12, %sp
-; NO-ATOMIC-NEXT:    rts
+; NO-ATOMIC-000-LABEL: atomicrmw_add_i8:
+; NO-ATOMIC-000:         .cfi_startproc
+; NO-ATOMIC-000-NEXT:  ; %bb.0:
+; NO-ATOMIC-000-NEXT:    suba.l #12, %sp
+; NO-ATOMIC-000-NEXT:    .cfi_def_cfa_offset -16
+; NO-ATOMIC-000-NEXT:    move.b (19,%sp), %d0
+; NO-ATOMIC-000-NEXT:    and.l #255, %d0
+; NO-ATOMIC-000-NEXT:    move.l %d0, (4,%sp)
+; NO-ATOMIC-000-NEXT:    move.l (20,%sp), (%sp)
+; NO-ATOMIC-000-NEXT:    jsr __sync_fetch_and_add_1
+; NO-ATOMIC-000-NEXT:    adda.l #12, %sp
+; NO-ATOMIC-000-NEXT:    rts
+;
+; NO-ATOMIC-010-LABEL: atomicrmw_add_i8:
+; NO-ATOMIC-010:         .cfi_startproc
+; NO-ATOMIC-010-NEXT:  ; %bb.0:
+; NO-ATOMIC-010-NEXT:    suba.l #12, %sp
+; NO-ATOMIC-010-NEXT:    .cfi_def_cfa_offset -16
+; NO-ATOMIC-010-NEXT:    move.b (19,%sp), %d0
+; NO-ATOMIC-010-NEXT:    and.l #255, %d0
+; NO-ATOMIC-010-NEXT:    move.l %d0, (4,%sp)
+; NO-ATOMIC-010-NEXT:    move.l (20,%sp), (%sp)
+; NO-ATOMIC-010-NEXT:    jsr __sync_fetch_and_add_1
+; NO-ATOMIC-010-NEXT:    adda.l #12, %sp
+; NO-ATOMIC-010-NEXT:    rts
 ;
 ; ATOMIC-LABEL: atomicrmw_add_i8:
 ; ATOMIC:         .cfi_startproc
@@ -39,7 +52,9 @@ define i8 @atomicrmw_add_i8(i8 %val, ptr %ptr) {
 ; ATOMIC-NEXT:    seq %d2
 ; ATOMIC-NEXT:    and.b #1, %d2
 ; ATOMIC-NEXT:    cmpi.b #0, %d2
+; ATOMIC-NEXT:    move.w %ccr, %d3
 ; ATOMIC-NEXT:    move.b %d0, %d2
+; ATOMIC-NEXT:    move.w %d3, %ccr
 ; ATOMIC-NEXT:    beq .LBB0_1
 ; ATOMIC-NEXT:  ; %bb.2: ; %atomicrmw.end
 ; ATOMIC-NEXT:    movem.l (0,%sp), %d2-%d3 ; 12-byte Folded Reload
@@ -50,18 +65,31 @@ define i8 @atomicrmw_add_i8(i8 %val, ptr %ptr) {
 }
 
 define i16 @atomicrmw_sub_i16(i16 %val, ptr %ptr) {
-; NO-ATOMIC-LABEL: atomicrmw_sub_i16:
-; NO-ATOMIC:         .cfi_startproc
-; NO-ATOMIC-NEXT:  ; %bb.0:
-; NO-ATOMIC-NEXT:    suba.l #12, %sp
-; NO-ATOMIC-NEXT:    .cfi_def_cfa_offset -16
-; NO-ATOMIC-NEXT:    move.w (18,%sp), %d0
-; NO-ATOMIC-NEXT:    and.l #65535, %d0
-; NO-ATOMIC-NEXT:    move.l %d0, (4,%sp)
-; NO-ATOMIC-NEXT:    move.l (20,%sp), (%sp)
-; NO-ATOMIC-NEXT:    jsr __sync_fetch_and_sub_2
-; NO-ATOMIC-NEXT:    adda.l #12, %sp
-; NO-ATOMIC-NEXT:    rts
+; NO-ATOMIC-000-LABEL: atomicrmw_sub_i16:
+; NO-ATOMIC-000:         .cfi_startproc
+; NO-ATOMIC-000-NEXT:  ; %bb.0:
+; NO-ATOMIC-000-NEXT:    suba.l #12, %sp
+; NO-ATOMIC-000-NEXT:    .cfi_def_cfa_offset -16
+; NO-ATOMIC-000-NEXT:    move.w (18,%sp), %d0
+; NO-ATOMIC-000-NEXT:    and.l #65535, %d0
+; NO-ATOMIC-000-NEXT:    move.l %d0, (4,%sp)
+; NO-ATOMIC-000-NEXT:    move.l (20,%sp), (%sp)
+; NO-ATOMIC-000-NEXT:    jsr __sync_fetch_and_sub_2
+; NO-ATOMIC-000-NEXT:    adda.l #12, %sp
+; NO-ATOMIC-000-NEXT:    rts
+;
+; NO-ATOMIC-010-LABEL: atomicrmw_sub_i16:
+; NO-ATOMIC-010:         .cfi_startproc
+; NO-ATOMIC-010-NEXT:  ; %bb.0:
+; NO-ATOMIC-010-NEXT:    suba.l #12, %sp
+; NO-ATOMIC-010-NEXT:    .cfi_def_cfa_offset -16
+; NO-ATOMIC-010-NEXT:    move.w (18,%sp), %d0
+; NO-ATOMIC-010-NEXT:    and.l #65535, %d0
+; NO-ATOMIC-010-NEXT:    move.l %d0, (4,%sp)
+; NO-ATOMIC-010-NEXT:    move.l (20,%sp), (%sp)
+; NO-ATOMIC-010-NEXT:    jsr __sync_fetch_and_sub_2
+; NO-ATOMIC-010-NEXT:    adda.l #12, %sp
+; NO-ATOMIC-010-NEXT:    rts
 ;
 ; ATOMIC-LABEL: atomicrmw_sub_i16:
 ; ATOMIC:         .cfi_startproc
@@ -83,7 +111,9 @@ define i16 @atomicrmw_sub_i16(i16 %val, ptr %ptr) {
 ; ATOMIC-NEXT:    seq %d2
 ; ATOMIC-NEXT:    and.b #1, %d2
 ; ATOMIC-NEXT:    cmpi.b #0, %d2
+; ATOMIC-NEXT:    move.w %ccr, %d3
 ; ATOMIC-NEXT:    move.w %d0, %d2
+; ATOMIC-NEXT:    move.w %d3, %ccr
 ; ATOMIC-NEXT:    beq .LBB1_1
 ; ATOMIC-NEXT:  ; %bb.2: ; %atomicrmw.end
 ; ATOMIC-NEXT:    movem.l (0,%sp), %d2-%d3 ; 12-byte Folded Reload
@@ -94,16 +124,27 @@ define i16 @atomicrmw_sub_i16(i16 %val, ptr %ptr) {
 }
 
 define i32 @atomicrmw_and_i32(i32 %val, ptr %ptr) {
-; NO-ATOMIC-LABEL: atomicrmw_and_i32:
-; NO-ATOMIC:         .cfi_startproc
-; NO-ATOMIC-NEXT:  ; %bb.0:
-; NO-ATOMIC-NEXT:    suba.l #12, %sp
-; NO-ATOMIC-NEXT:    .cfi_def_cfa_offset -16
-; NO-ATOMIC-NEXT:    move.l (16,%sp), (4,%sp)
-; NO-ATOMIC-NEXT:    move.l (20,%sp), (%sp)
-; NO-ATOMIC-NEXT:    jsr __sync_fetch_and_and_4
-; NO-ATOMIC-NEXT:    adda.l #12, %sp
-; NO-ATOMIC-NEXT:    rts
+; NO-ATOMIC-000-LABEL: atomicrmw_and_i32:
+; NO-ATOMIC-000:         .cfi_startproc
+; NO-ATOMIC-000-NEXT:  ; %bb.0:
+; NO-ATOMIC-000-NEXT:    suba.l #12, %sp
+; NO-ATOMIC-000-NEXT:    .cfi_def_cfa_offset -16
+; NO-ATOMIC-000-NEXT:    move.l (16,%sp), (4,%sp)
+; NO-ATOMIC-000-NEXT:    move.l (20,%sp), (%sp)
+; NO-ATOMIC-000-NEXT:    jsr __sync_fetch_and_and_4
+; NO-ATOMIC-000-NEXT:    adda.l #12, %sp
+; NO-ATOMIC-000-NEXT:    rts
+;
+; NO-ATOMIC-010-LABEL: atomicrmw_and_i32:
+; NO-ATOMIC-010:         .cfi_startproc
+; NO-ATOMIC-010-NEXT:  ; %bb.0:
+; NO-ATOMIC-010-NEXT:    suba.l #12, %sp
+; NO-ATOMIC-010-NEXT:    .cfi_def_cfa_offset -16
+; NO-ATOMIC-010-NEXT:    move.l (16,%sp), (4,%sp)
+; NO-ATOMIC-010-NEXT:    move.l (20,%sp), (%sp)
+; NO-ATOMIC-010-NEXT:    jsr __sync_fetch_and_and_4
+; NO-ATOMIC-010-NEXT:    adda.l #12, %sp
+; NO-ATOMIC-010-NEXT:    rts
 ;
 ; ATOMIC-LABEL: atomicrmw_and_i32:
 ; ATOMIC:         .cfi_startproc
@@ -125,7 +166,9 @@ define i32 @atomicrmw_and_i32(i32 %val, ptr %ptr) {
 ; ATOMIC-NEXT:    seq %d2
 ; ATOMIC-NEXT:    and.b #1, %d2
 ; ATOMIC-NEXT:    cmpi.b #0, %d2
+; ATOMIC-NEXT:    move.w %ccr, %d3
 ; ATOMIC-NEXT:    move.l %d0, %d2
+; ATOMIC-NEXT:    move.w %d3, %ccr
 ; ATOMIC-NEXT:    beq .LBB2_1
 ; ATOMIC-NEXT:  ; %bb.2: ; %atomicrmw.end
 ; ATOMIC-NEXT:    movem.l (0,%sp), %d2-%d3 ; 12-byte Folded Reload
@@ -136,18 +179,31 @@ define i32 @atomicrmw_and_i32(i32 %val, ptr %ptr) {
 }
 
 define i64 @atomicrmw_xor_i64(i64 %val, ptr %ptr) {
-; NO-ATOMIC-LABEL: atomicrmw_xor_i64:
-; NO-ATOMIC:         .cfi_startproc
-; NO-ATOMIC-NEXT:  ; %bb.0:
-; NO-ATOMIC-NEXT:    suba.l #20, %sp
-; NO-ATOMIC-NEXT:    .cfi_def_cfa_offset -24
-; NO-ATOMIC-NEXT:    move.l #3, (12,%sp)
-; NO-ATOMIC-NEXT:    move.l (28,%sp), (8,%sp)
-; NO-ATOMIC-NEXT:    move.l (24,%sp), (4,%sp)
-; NO-ATOMIC-NEXT:    move.l (32,%sp), (%sp)
-; NO-ATOMIC-NEXT:    jsr __atomic_fetch_xor_8
-; NO-ATOMIC-NEXT:    adda.l #20, %sp
-; NO-ATOMIC-NEXT:    rts
+; NO-ATOMIC-000-LABEL: atomicrmw_xor_i64:
+; NO-ATOMIC-000:         .cfi_startproc
+; NO-ATOMIC-000-NEXT:  ; %bb.0:
+; NO-ATOMIC-000-NEXT:    suba.l #20, %sp
+; NO-ATOMIC-000-NEXT:    .cfi_def_cfa_offset -24
+; NO-ATOMIC-000-NEXT:    move.l #3, (12,%sp)
+; NO-ATOMIC-000-NEXT:    move.l (28,%sp), (8,%sp)
+; NO-ATOMIC-000-NEXT:    move.l (24,%sp), (4,%sp)
+; NO-ATOMIC-000-NEXT:    move.l (32,%sp), (%sp)
+; NO-ATOMIC-000-NEXT:    jsr __atomic_fetch_xor_8
+; NO-ATOMIC-000-NEXT:    adda.l #20, %sp
+; NO-ATOMIC-000-NEXT:    rts
+;
+; NO-ATOMIC-010-LABEL: atomicrmw_xor_i64:
+; NO-ATOMIC-010:         .cfi_startproc
+; NO-ATOMIC-010-NEXT:  ; %bb.0:
+; NO-ATOMIC-010-NEXT:    suba.l #20, %sp
+; NO-ATOMIC-010-NEXT:    .cfi_def_cfa_offset -24
+; NO-ATOMIC-010-NEXT:    move.l #3, (12,%sp)
+; NO-ATOMIC-010-NEXT:    move.l (28,%sp), (8,%sp)
+; NO-ATOMIC-010-NEXT:    move.l (24,%sp), (4,%sp)
+; NO-ATOMIC-010-NEXT:    move.l (32,%sp), (%sp)
+; NO-ATOMIC-010-NEXT:    jsr __atomic_fetch_xor_8
+; NO-ATOMIC-010-NEXT:    adda.l #20, %sp
+; NO-ATOMIC-010-NEXT:    rts
 ;
 ; ATOMIC-LABEL: atomicrmw_xor_i64:
 ; ATOMIC:         .cfi_startproc
@@ -166,18 +222,31 @@ define i64 @atomicrmw_xor_i64(i64 %val, ptr %ptr) {
 }
 
 define i8 @atomicrmw_or_i8(i8 %val, ptr %ptr) {
-; NO-ATOMIC-LABEL: atomicrmw_or_i8:
-; NO-ATOMIC:         .cfi_startproc
-; NO-ATOMIC-NEXT:  ; %bb.0:
-; NO-ATOMIC-NEXT:    suba.l #12, %sp
-; NO-ATOMIC-NEXT:    .cfi_def_cfa_offset -16
-; NO-ATOMIC-NEXT:    move.b (19,%sp), %d0
-; NO-ATOMIC-NEXT:    and.l #255, %d0
-; NO-ATOMIC-NEXT:    move.l %d0, (4,%sp)
-; NO-ATOMIC-NEXT:    move.l (20,%sp), (%sp)
-; NO-ATOMIC-NEXT:    jsr __sync_fetch_and_or_1...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list