Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle moves of non-16 size to/from CCR #108581

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/lib/Target/M68k/M68kExpandPseudo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 7 additions & 1 deletion llvm/lib/Target/M68k/M68kInstrData.td
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ class MxMoveToCCRPseudo<MxOperand MEMOp>

let mayLoad = 1 in
foreach AM = MxMoveSupportedAMs in {
def MOV32c # AM : MxMoveToCCRPseudo<!cast<MxOpBundle>("MxOp32AddrMode_"#AM).Op>;
def MOV16c # AM : MxMoveToCCR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
def MOV8c # AM : MxMoveToCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>;
Expand Down Expand Up @@ -419,10 +420,15 @@ 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
foreach AM = MxMoveSupportedAMs in {
def MOV32 # AM # c
: MxMoveFromCCR_M<!cast<MxOpBundle>("MxOp32AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;
def MOV16 # AM # c
: MxMoveFromCCR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;
Expand All @@ -432,7 +438,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
44 changes: 33 additions & 11 deletions llvm/lib/Target/M68k/M68kInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cassert>
#include <functional>
#include <iterator>

using namespace llvm;

Expand Down Expand Up @@ -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)
Expand All @@ -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;
}

Expand Down Expand Up @@ -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");

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
}