Skip to content

Commit

Permalink
[M68k] Handle 16 bit MOVs to and from CCR (#114714)
Browse files Browse the repository at this point in the history
Builds on @TechnoElf 's CCR MOV pr
#107591 and adds some tests.

Fixes #106210.

---------

Co-authored-by: TechnoElf <[email protected]>
  • Loading branch information
knickish and TechnoElf authored Nov 27, 2024
1 parent 1e3e199 commit c29e895
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 13 deletions.
4 changes: 3 additions & 1 deletion llvm/lib/Target/M68k/M68kInstrData.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
39 changes: 28 additions & 11 deletions llvm/lib/Target/M68k/M68kInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}

Expand Down Expand Up @@ -757,13 +760,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");

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/M68k/M68kRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
126 changes: 126 additions & 0 deletions llvm/test/CodeGen/M68k/Control/non-cmov-switch.ll
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit c29e895

Please sign in to comment.