From 9be48e599f11730c3b2a705a2622a4f3c70e144e Mon Sep 17 00:00:00 2001 From: kirk Date: Fri, 13 Sep 2024 14:34:06 +0000 Subject: [PATCH] add pseudo instrs for 8 and 32 bit src/dst ccr moves and expand them to 16 bit instrs --- llvm/lib/Target/M68k/M68kExpandPseudo.cpp | 1 + llvm/lib/Target/M68k/M68kInstrData.td | 8 +- llvm/lib/Target/M68k/M68kInstrInfo.cpp | 44 ++++-- llvm/lib/Target/M68k/M68kRegisterInfo.h | 2 +- .../CodeGen/M68k/Control/non-cmov-switch.ll | 126 ++++++++++++++++++ 5 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll diff --git a/llvm/lib/Target/M68k/M68kExpandPseudo.cpp b/llvm/lib/Target/M68k/M68kExpandPseudo.cpp index c7fdd7d7c3502..0e9878b9a8ff9 100644 --- a/llvm/lib/Target/M68k/M68kExpandPseudo.cpp +++ b/llvm/lib/Target/M68k/M68kExpandPseudo.cpp @@ -190,6 +190,7 @@ bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case M68k::MOV8cd: return TII->ExpandCCR(MIB, /*IsToCCR=*/true); + case M68k::MOV8dc: return TII->ExpandCCR(MIB, /*IsToCCR=*/false); diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td index dc777a933e278..af12c079a4741 100644 --- a/llvm/lib/Target/M68k/M68kInstrData.td +++ b/llvm/lib/Target/M68k/M68kInstrData.td @@ -385,6 +385,7 @@ class MxMoveToCCRPseudo let mayLoad = 1 in foreach AM = MxMoveSupportedAMs in { + def MOV32c # AM : MxMoveToCCRPseudo("MxOp32AddrMode_"#AM).Op>; def MOV16c # AM : MxMoveToCCR("MxOp16AddrMode_"#AM).Op, !cast("MxMoveSrcOpEnc_"#AM)>; def MOV8c # AM : MxMoveToCCRPseudo("MxOp8AddrMode_"#AM).Op>; @@ -419,10 +420,15 @@ class MxMoveFromCCR_M class MxMoveFromCCRPseudo : MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>; +class MxMoveFromCCR_RPseudo + : MxPseudo<(outs MEMOp:$dst), (ins CCRC:$src)>; } // let Uses = [CCR] let mayStore = 1 in foreach AM = MxMoveSupportedAMs in { + def MOV32 # AM # c + : MxMoveFromCCR_M("MxOp32AddrMode_"#AM).Op, + !cast("MxMoveDstOpEnc_"#AM)>; def MOV16 # AM # c : MxMoveFromCCR_M("MxOp16AddrMode_"#AM).Op, !cast("MxMoveDstOpEnc_"#AM)>; @@ -432,7 +438,7 @@ foreach AM = MxMoveSupportedAMs in { // Only data register is allowed. def MOV16dc : MxMoveFromCCR_R; -def MOV8dc : MxMoveFromCCRPseudo; +def MOV8dc : MxMoveFromCCR_RPseudo; //===----------------------------------------------------------------------===// // LEA diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp index 2d9285f89b74a..cbea60440205e 100644 --- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp +++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp @@ -23,12 +23,16 @@ #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" +#include #include +#include using namespace llvm; @@ -571,6 +575,17 @@ bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB, } bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const { + switch (MIB->getOpcode()) { + case M68k::MOV8cd: { + // Promote used register to the next class + auto &Opd = MIB->getOperand(1); + Opd.setReg(getRegisterInfo().getMatchingSuperReg( + Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass)); + break; + } + default: + break; + } // Replace the pseudo instruction with the real one if (IsToCCR) @@ -579,11 +594,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; } @@ -757,13 +767,25 @@ 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 { + LLVM_DEBUG(dbgs() << "Cannot copy CCR to " << RI.getName(DstReg) << "(" + << RI.getRegClass(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 { + 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"); diff --git a/llvm/lib/Target/M68k/M68kRegisterInfo.h b/llvm/lib/Target/M68k/M68kRegisterInfo.h index 0cfab150d0c84..5131768345366 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 0000000000000..90d2be017ecdb --- /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 +}