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 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 @@ -432,7 +434,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 2d9285f89b74ae..63404645209508 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; } @@ -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"); 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 +}