[llvm] [M68k] Handle 16 bit MOVs to and from CCR (PR #114714)

via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 10 21:01:56 PST 2024


https://github.com/knickish updated https://github.com/llvm/llvm-project/pull/114714

>From 0f92de6b34c50136118afea87bd9d56a8467add0 Mon Sep 17 00:00:00 2001
From: TechnoElf <technoelf at undertheprinter.com>
Date: Fri, 6 Sep 2024 16:04:22 +0200
Subject: [PATCH 1/2] [M68k] allow 16-bit registers for MOVE to/from CCR

---
 llvm/lib/Target/M68k/M68kInstrInfo.cpp | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
index 2d9285f89b74ae..46deeef49b2ef4 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
@@ -757,13 +757,27 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   bool ToSR = DstReg == M68k::SR;
 
   if (FromCCR) {
-    assert(M68k::DR8RegClass.contains(DstReg) &&
-           "Need DR8 register to copy CCR");
-    Opc = M68k::MOV8dc;
+    if (M68k::DR8RegClass.contains(DstReg))
+      Opc = M68k::MOV8dc;
+    else if (M68k::DR16RegClass.contains(DstReg))
+      Opc = M68k::MOV16dc;
+    else if (M68k::DR32RegClass.contains(DstReg))
+      Opc = 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) {
-    assert(M68k::DR8RegClass.contains(SrcReg) &&
-           "Need DR8 register to copy CCR");
-    Opc = M68k::MOV8cd;
+    if (M68k::DR8RegClass.contains(SrcReg))
+      Opc = M68k::MOV8cd;
+    else if (M68k::DR16RegClass.contains(SrcReg))
+      Opc = M68k::MOV16cd;
+    else if (M68k::DR32RegClass.contains(SrcReg))
+      Opc = M68k::MOV16cd;
+    else {
+      LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to CCR\n");
+      llvm_unreachable("Invalid register for MOVE to CCR");
+    }
   } else if (FromSR || ToSR)
     llvm_unreachable("Cannot emit SR copy instruction");
 

>From 5fc6665a7a6ee05144b29c98a983aaae702f32cd Mon Sep 17 00:00:00 2001
From: kirk <knickish at gmail.com>
Date: Fri, 13 Sep 2024 14:34:06 +0000
Subject: [PATCH 2/2] [M68k] add test and change default copy size for ccr

---
 llvm/lib/Target/M68k/M68kInstrData.td         |   4 +-
 llvm/lib/Target/M68k/M68kInstrInfo.cpp        |  41 +++---
 llvm/lib/Target/M68k/M68kRegisterInfo.h       |   2 +-
 .../CodeGen/M68k/Control/non-cmov-switch.ll   | 126 ++++++++++++++++++
 4 files changed, 152 insertions(+), 21 deletions(-)
 create mode 100644 llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll

diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index dc777a933e2786..adaa8c85eefb9c 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -419,6 +419,8 @@ class MxMoveFromCCR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>
 
 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
@@ -432,7 +434,7 @@ foreach AM = MxMoveSupportedAMs in {
 
 // Only data register is allowed.
 def MOV16dc : MxMoveFromCCR_R;
-def MOV8dc  : MxMoveFromCCRPseudo<MxOp8AddrMode_d.Op>;
+def MOV8dc  : MxMoveFromCCR_RPseudo<MxOp8AddrMode_d.Op>;
 
 //===----------------------------------------------------------------------===//
 // LEA
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
index 46deeef49b2ef4..f7219c248270ab 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp
@@ -23,7 +23,9 @@
 #include "llvm/CodeGen/LivePhysRegs.h"
 #include "llvm/CodeGen/LiveVariables.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGenTypes/MachineValueType.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Regex.h"
@@ -571,6 +573,12 @@ bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB,
 }
 
 bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
+  if (MIB->getOpcode() == M68k::MOV8cd) {
+    // Promote used register to the next class
+    MachineOperand &Opd = MIB->getOperand(1);
+    Opd.setReg(getRegisterInfo().getMatchingSuperReg(
+        Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
+  }
 
   // Replace the pseudo instruction with the real one
   if (IsToCCR)
@@ -579,11 +587,6 @@ bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
     // FIXME M68010 or later is required
     MIB->setDesc(get(M68k::MOV16dc));
 
-  // Promote used register to the next class
-  auto &Opd = MIB->getOperand(1);
-  Opd.setReg(getRegisterInfo().getMatchingSuperReg(
-      Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
-
   return true;
 }
 
@@ -729,8 +732,8 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     return;
   }
 
-  // Now deal with asymmetrically sized copies. The cases that follow are upcast
-  // moves.
+  // 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
@@ -757,24 +760,24 @@ void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   bool ToSR = DstReg == M68k::SR;
 
   if (FromCCR) {
-    if (M68k::DR8RegClass.contains(DstReg))
+    if (M68k::DR8RegClass.contains(DstReg)) {
       Opc = M68k::MOV8dc;
-    else if (M68k::DR16RegClass.contains(DstReg))
+    } else if (M68k::DR16RegClass.contains(DstReg)) {
       Opc = M68k::MOV16dc;
-    else if (M68k::DR32RegClass.contains(DstReg))
+    } else if (M68k::DR32RegClass.contains(DstReg)) {
       Opc = M68k::MOV16dc;
-    else {
+    } else {
       LLVM_DEBUG(dbgs() << "Cannot copy CCR to " << RI.getName(DstReg) << '\n');
       llvm_unreachable("Invalid register for MOVE from CCR");
     }
   } else if (ToCCR) {
-    if (M68k::DR8RegClass.contains(SrcReg))
+    if (M68k::DR8RegClass.contains(SrcReg)) {
       Opc = M68k::MOV8cd;
-    else if (M68k::DR16RegClass.contains(SrcReg))
+    } else if (M68k::DR16RegClass.contains(SrcReg)) {
       Opc = M68k::MOV16cd;
-    else if (M68k::DR32RegClass.contains(SrcReg))
+    } else if (M68k::DR32RegClass.contains(SrcReg)) {
       Opc = M68k::MOV16cd;
-    else {
+    } else {
       LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to CCR\n");
       llvm_unreachable("Invalid register for MOVE to CCR");
     }
@@ -886,10 +889,10 @@ unsigned M68kInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
   //
   // NOTE
   // Normally M68k uses A5 register as global base pointer but this will
-  // create unnecessary spill if we use less then 4 registers in code; since A5
-  // is callee-save anyway we could try to allocate caller-save first and if
-  // lucky get one, otherwise it does not really matter which callee-save to
-  // use.
+  // create unnecessary spill if we use less then 4 registers in code; since
+  // A5 is callee-save anyway we could try to allocate caller-save first and
+  // if lucky get one, otherwise it does not really matter which callee-save
+  // to use.
   MachineRegisterInfo &RegInfo = MF->getRegInfo();
   GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass);
   MxFI->setGlobalBaseReg(GlobalBaseReg);
diff --git a/llvm/lib/Target/M68k/M68kRegisterInfo.h b/llvm/lib/Target/M68k/M68kRegisterInfo.h
index 0cfab150d0c84b..51317683453666 100644
--- a/llvm/lib/Target/M68k/M68kRegisterInfo.h
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.h
@@ -101,7 +101,7 @@ class M68kRegisterInfo : public M68kGenRegisterInfo {
   const TargetRegisterClass *
   getCrossCopyRegClass(const TargetRegisterClass *RC) const override {
     if (RC == &M68k::CCRCRegClass)
-      return &M68k::DR32RegClass;
+      return &M68k::DR16RegClass;
     return RC;
   }
 
diff --git a/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll b/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
new file mode 100644
index 00000000000000..90d2be017ecdb2
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
@@ -0,0 +1,126 @@
+; 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
+
+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:    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
+start:
+  %2 = icmp eq i32 %self, 0
+  %3 = select i1 %2, i32 0, i32 1
+  switch i32 %3, label %exit [
+    i32 0, label %nonnull
+    i32 1, label %null
+  ]
+
+nonnull:                                              ; preds = %start
+  store ptr %value, ptr null, align 2
+  br label %exit
+
+null:                                              ; preds = %start
+  store ptr %value, ptr null, align 2
+  br label %exit
+
+exit:                                              ; preds = %nonnull, %null
+  ret void
+}
+
+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:    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
+start:
+  %2 = icmp eq i16 %self, 0
+  %3 = select i1 %2, i16 0, i16 1
+  switch i16 %3, label %exit [
+    i16 0, label %nonnull
+    i16 1, label %null
+  ]
+
+nonnull:                                              ; preds = %start
+  store ptr %value, ptr null, align 2
+  br label %exit
+
+null:                                              ; preds = %start
+  store ptr %value, ptr null, align 2
+  br label %exit
+
+exit:                                              ; preds = %nonnull, %null
+  ret void
+}
+
+define internal void @select_i8(i8 %self, ptr nonnull %value) {
+; CHECK-LABEL: select_i8:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0: ; %start
+; CHECK-NEXT:    move.l (8,%sp), %d0
+; CHECK-NEXT:    cmpi.b #0, (7,%sp)
+; CHECK-NEXT:    sne %d1
+; CHECK-NEXT:    bne .LBB2_2
+; CHECK-NEXT:  ; %bb.1: ; %start
+; 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:    rts
+start:
+  %2 = icmp eq i8 %self, 0
+  %3 = select i1 %2, i8 0, i8 1
+  switch i8 %3, label %exit [
+    i8 0, label %nonnull
+    i8 1, label %null
+  ]
+
+nonnull:                                              ; preds = %start
+  store ptr %value, ptr null, align 2
+  br label %exit
+
+null:                                              ; preds = %start
+  store ptr %value, ptr null, align 2
+  br label %exit
+
+exit:                                              ; preds = %nonnull, %null
+  ret void
+}



More information about the llvm-commits mailing list